зеркало из https://github.com/mozilla/pjs.git
added pseudo style support
added debug list of context graph
This commit is contained in:
Родитель
12db5cfc8d
Коммит
8cb0400608
|
@ -23,7 +23,6 @@
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
|
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIStyleSetIID, NS_ISTYLE_SET_IID);
|
static NS_DEFINE_IID(kIStyleSetIID, NS_ISTYLE_SET_IID);
|
||||||
|
|
||||||
class ContextKey : public nsHashKey {
|
class ContextKey : public nsHashKey {
|
||||||
|
@ -196,6 +195,14 @@ public:
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame);
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
|
virtual nsIStyleContext* ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
|
virtual nsIStyleContext* ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
// xxx style rules enumeration
|
// xxx style rules enumeration
|
||||||
|
|
||||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0);
|
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0);
|
||||||
|
@ -208,12 +215,20 @@ private:
|
||||||
protected:
|
protected:
|
||||||
virtual ~StyleSetImpl();
|
virtual ~StyleSetImpl();
|
||||||
PRBool EnsureArray(nsISupportsArray** aArray);
|
PRBool EnsureArray(nsISupportsArray** aArray);
|
||||||
|
nsIStyleContext* GetContext(nsIPresContext* aPresContext, nsIFrame* aParentFrame,
|
||||||
|
nsIStyleContext* aParentContext, nsISupportsArray* aRules);
|
||||||
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
||||||
nsIPresContext* aPresContext,
|
nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame,
|
nsIFrame* aParentFrame,
|
||||||
nsISupportsArray* aResults);
|
nsISupportsArray* aResults);
|
||||||
|
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
||||||
|
nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame,
|
||||||
|
nsISupportsArray* aResults);
|
||||||
void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets);
|
void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets);
|
||||||
|
void ListContexts(FILE* out, PRInt32 aIndent);
|
||||||
|
|
||||||
nsISupportsArray* mOverrideSheets;
|
nsISupportsArray* mOverrideSheets;
|
||||||
nsISupportsArray* mDocSheets;
|
nsISupportsArray* mDocSheets;
|
||||||
|
@ -445,13 +460,33 @@ PRInt32 StyleSetImpl::RulesMatching(nsISupportsArray* aSheets,
|
||||||
return ruleCount;
|
return ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::GetContext(nsIPresContext* aPresContext, nsIFrame* aParentFrame,
|
||||||
|
nsIStyleContext* aParentContext, nsISupportsArray* aRules)
|
||||||
|
{
|
||||||
|
// check for cached ruleSet to context or create
|
||||||
|
ContextKey tempKey(aParentContext, aRules);
|
||||||
|
nsIStyleContext* result = (nsIStyleContext*)mStyleContexts.Get(&tempKey);
|
||||||
|
if (nsnull == result) {
|
||||||
|
if (NS_OK == NS_NewStyleContext(&result, aRules, aPresContext, aParentFrame)) {
|
||||||
|
tempKey.SetContext(result);
|
||||||
|
mStyleContexts.Put(&tempKey, result); // hashtable clones key, so this is OK (table gets first ref)
|
||||||
|
NS_ADDREF(result); // add ref for the caller
|
||||||
|
//fprintf(stdout, "+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_ADDREF(result);
|
||||||
|
//fprintf(stdout, "-");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame)
|
nsIFrame* aParentFrame)
|
||||||
{
|
{
|
||||||
nsIStyleContext* result = nsnull;
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
nsIStyleContext* parentContext = nsnull;
|
|
||||||
|
|
||||||
if (nsnull != aParentFrame) {
|
if (nsnull != aParentFrame) {
|
||||||
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
@ -468,21 +503,96 @@ nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
||||||
ruleCount += RulesMatching(mDocSheets, aPresContext, aContent, aParentFrame, rules);
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aContent, aParentFrame, rules);
|
||||||
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aContent, aParentFrame, rules);
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aContent, aParentFrame, rules);
|
||||||
|
|
||||||
// then check for cached ruleSet to context or create
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
ContextKey tempKey(parentContext, rules);
|
|
||||||
result = (nsIStyleContext*)mStyleContexts.Get(&tempKey);
|
NS_RELEASE(rules);
|
||||||
if (nsnull == result) {
|
}
|
||||||
if (NS_OK == NS_NewStyleContext(&result, rules, aPresContext, aContent, aParentFrame)) {
|
|
||||||
tempKey.SetContext(result);
|
NS_IF_RELEASE(parentContext);
|
||||||
mStyleContexts.Put(&tempKey, result); // hashtable clones key, so this is OK (table gets first ref)
|
|
||||||
NS_ADDREF(result); // add ref for the caller
|
return result;
|
||||||
//fprintf(stdout, "+");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
PRInt32 StyleSetImpl::RulesMatching(nsISupportsArray* aSheets,
|
||||||
|
nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame,
|
||||||
|
nsISupportsArray* aResults)
|
||||||
|
{
|
||||||
|
PRInt32 ruleCount = 0;
|
||||||
|
|
||||||
|
if (nsnull != aSheets) {
|
||||||
|
PRInt32 sheetCount = aSheets->Count();
|
||||||
|
PRInt32 index;
|
||||||
|
for (index = 0; index < sheetCount; index++) {
|
||||||
|
nsIStyleSheet* sheet = (nsIStyleSheet*)aSheets->ElementAt(index);
|
||||||
|
ruleCount += sheet->RulesMatching(aPresContext, aPseudoTag, aParentFrame,
|
||||||
|
aResults);
|
||||||
|
NS_RELEASE(sheet);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
NS_ADDREF(result);
|
return ruleCount;
|
||||||
//fprintf(stdout, "-");
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame)
|
||||||
|
{
|
||||||
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
|
|
||||||
|
if (nsnull != aParentFrame) {
|
||||||
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
NS_ASSERTION(nsnull != parentContext, "parent must have style context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// want to check parent frame's context for cached child context first
|
||||||
|
|
||||||
|
// then do a brute force rule search
|
||||||
|
|
||||||
|
nsISupportsArray* rules = nsnull;
|
||||||
|
if (NS_OK == NS_NewISupportsArray(&rules)) {
|
||||||
|
PRInt32 ruleCount = RulesMatching(mOverrideSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
|
||||||
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
|
|
||||||
|
NS_RELEASE(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IF_RELEASE(parentContext);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame)
|
||||||
|
{
|
||||||
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
|
|
||||||
|
if (nsnull != aParentFrame) {
|
||||||
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
NS_ASSERTION(nsnull != parentContext, "parent must have style context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// want to check parent frame's context for cached child context first
|
||||||
|
|
||||||
|
// then do a brute force rule search
|
||||||
|
|
||||||
|
nsISupportsArray* rules = nsnull;
|
||||||
|
if (NS_OK == NS_NewISupportsArray(&rules)) {
|
||||||
|
PRInt32 ruleCount = RulesMatching(mOverrideSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
|
||||||
|
if (0 < ruleCount) {
|
||||||
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_RELEASE(rules);
|
NS_RELEASE(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,6 +622,135 @@ void StyleSetImpl::List(FILE* out, PRInt32 aIndent)
|
||||||
List(out, aIndent, mBackstopSheets);
|
List(out, aIndent, mBackstopSheets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ContextNode {
|
||||||
|
nsIStyleContext* mContext;
|
||||||
|
ContextNode* mNext;
|
||||||
|
ContextNode* mChild;
|
||||||
|
ContextNode(nsIStyleContext* aContext)
|
||||||
|
{
|
||||||
|
mContext = aContext;
|
||||||
|
mNext = nsnull;
|
||||||
|
mChild = nsnull;
|
||||||
|
}
|
||||||
|
~ContextNode(void)
|
||||||
|
{
|
||||||
|
if (nsnull != mNext) {
|
||||||
|
delete mNext;
|
||||||
|
}
|
||||||
|
if (nsnull != mChild) {
|
||||||
|
delete mChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ContextNode* gRootNode;
|
||||||
|
|
||||||
|
static ContextNode* FindNode(nsIStyleContext* aContext, ContextNode* aStart)
|
||||||
|
{
|
||||||
|
ContextNode* node = aStart;
|
||||||
|
while (nsnull != node) {
|
||||||
|
if (node->mContext == aContext) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (nsnull != node->mChild) {
|
||||||
|
ContextNode* result = FindNode(aContext, node->mChild);
|
||||||
|
if (nsnull != result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GatherContexts(nsHashKey *aKey, void *aData)
|
||||||
|
{
|
||||||
|
PRBool result = PR_TRUE;
|
||||||
|
|
||||||
|
nsIStyleContext* context = (nsIStyleContext*)aData;
|
||||||
|
nsIStyleContext* parent = context->GetParent();
|
||||||
|
ContextNode* node = new ContextNode(context);
|
||||||
|
|
||||||
|
if (nsnull == gRootNode) {
|
||||||
|
gRootNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nsnull == parent) { // found real root, replace temp
|
||||||
|
node->mNext = gRootNode; // orphan the old root
|
||||||
|
gRootNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ContextNode* parentNode = FindNode(parent, gRootNode);
|
||||||
|
if (nsnull == parentNode) { // hang orhpans off root
|
||||||
|
node->mNext = gRootNode->mNext;
|
||||||
|
gRootNode->mNext = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node->mNext = parentNode->mChild;
|
||||||
|
parentNode->mChild = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// graft orphans
|
||||||
|
ContextNode* prevOrphan = nsnull;
|
||||||
|
ContextNode* orphan = gRootNode;
|
||||||
|
while (nsnull != orphan) {
|
||||||
|
nsIStyleContext* orphanParent = orphan->mContext->GetParent();
|
||||||
|
if (orphanParent == context) { // found our child
|
||||||
|
if (orphan == gRootNode) {
|
||||||
|
gRootNode = orphan->mNext;
|
||||||
|
orphan->mNext = node->mChild;
|
||||||
|
node->mChild = orphan;
|
||||||
|
orphan = gRootNode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ContextNode* foundling = orphan;
|
||||||
|
orphan = orphan->mNext;
|
||||||
|
prevOrphan->mNext = orphan;
|
||||||
|
foundling->mNext = node->mChild;
|
||||||
|
node->mChild = foundling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prevOrphan = orphan;
|
||||||
|
orphan = orphan->mNext;
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(orphanParent);
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(parent);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRInt32 ListNode(ContextNode* aNode, FILE* out, PRInt32 aIndent)
|
||||||
|
{
|
||||||
|
PRInt32 count = 0;
|
||||||
|
ContextNode* node = aNode;
|
||||||
|
while (nsnull != node) {
|
||||||
|
node->mContext->List(out, aIndent);
|
||||||
|
count++;
|
||||||
|
if (nsnull != node->mChild) {
|
||||||
|
nsIStyleContext* childParent = node->mChild->mContext->GetParent();
|
||||||
|
NS_ASSERTION(childParent == node->mContext, "broken graph");
|
||||||
|
NS_RELEASE(childParent);
|
||||||
|
count += ListNode(node->mChild, out, aIndent + 1);
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyleSetImpl::ListContexts(FILE* out, PRInt32 aIndent)
|
||||||
|
{
|
||||||
|
mStyleContexts.Enumerate(GatherContexts);
|
||||||
|
NS_ASSERTION(gRootNode->mNext == nsnull, "dangling orphan");
|
||||||
|
|
||||||
|
PRInt32 listCount = ListNode(gRootNode, out, aIndent);
|
||||||
|
NS_ASSERTION(listCount == mStyleContexts.Count(), "graph incomplete");
|
||||||
|
|
||||||
|
delete gRootNode;
|
||||||
|
gRootNode = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_LAYOUT nsresult
|
NS_LAYOUT nsresult
|
||||||
NS_NewStyleSet(nsIStyleSet** aInstancePtrResult)
|
NS_NewStyleSet(nsIStyleSet** aInstancePtrResult)
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
|
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIStyleSetIID, NS_ISTYLE_SET_IID);
|
static NS_DEFINE_IID(kIStyleSetIID, NS_ISTYLE_SET_IID);
|
||||||
|
|
||||||
class ContextKey : public nsHashKey {
|
class ContextKey : public nsHashKey {
|
||||||
|
@ -196,6 +195,14 @@ public:
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame);
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
|
virtual nsIStyleContext* ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
|
virtual nsIStyleContext* ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
// xxx style rules enumeration
|
// xxx style rules enumeration
|
||||||
|
|
||||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0);
|
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0);
|
||||||
|
@ -208,12 +215,20 @@ private:
|
||||||
protected:
|
protected:
|
||||||
virtual ~StyleSetImpl();
|
virtual ~StyleSetImpl();
|
||||||
PRBool EnsureArray(nsISupportsArray** aArray);
|
PRBool EnsureArray(nsISupportsArray** aArray);
|
||||||
|
nsIStyleContext* GetContext(nsIPresContext* aPresContext, nsIFrame* aParentFrame,
|
||||||
|
nsIStyleContext* aParentContext, nsISupportsArray* aRules);
|
||||||
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
||||||
nsIPresContext* aPresContext,
|
nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame,
|
nsIFrame* aParentFrame,
|
||||||
nsISupportsArray* aResults);
|
nsISupportsArray* aResults);
|
||||||
|
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
||||||
|
nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame,
|
||||||
|
nsISupportsArray* aResults);
|
||||||
void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets);
|
void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets);
|
||||||
|
void ListContexts(FILE* out, PRInt32 aIndent);
|
||||||
|
|
||||||
nsISupportsArray* mOverrideSheets;
|
nsISupportsArray* mOverrideSheets;
|
||||||
nsISupportsArray* mDocSheets;
|
nsISupportsArray* mDocSheets;
|
||||||
|
@ -445,13 +460,33 @@ PRInt32 StyleSetImpl::RulesMatching(nsISupportsArray* aSheets,
|
||||||
return ruleCount;
|
return ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::GetContext(nsIPresContext* aPresContext, nsIFrame* aParentFrame,
|
||||||
|
nsIStyleContext* aParentContext, nsISupportsArray* aRules)
|
||||||
|
{
|
||||||
|
// check for cached ruleSet to context or create
|
||||||
|
ContextKey tempKey(aParentContext, aRules);
|
||||||
|
nsIStyleContext* result = (nsIStyleContext*)mStyleContexts.Get(&tempKey);
|
||||||
|
if (nsnull == result) {
|
||||||
|
if (NS_OK == NS_NewStyleContext(&result, aRules, aPresContext, aParentFrame)) {
|
||||||
|
tempKey.SetContext(result);
|
||||||
|
mStyleContexts.Put(&tempKey, result); // hashtable clones key, so this is OK (table gets first ref)
|
||||||
|
NS_ADDREF(result); // add ref for the caller
|
||||||
|
//fprintf(stdout, "+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_ADDREF(result);
|
||||||
|
//fprintf(stdout, "-");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame)
|
nsIFrame* aParentFrame)
|
||||||
{
|
{
|
||||||
nsIStyleContext* result = nsnull;
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
nsIStyleContext* parentContext = nsnull;
|
|
||||||
|
|
||||||
if (nsnull != aParentFrame) {
|
if (nsnull != aParentFrame) {
|
||||||
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
@ -468,21 +503,96 @@ nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
||||||
ruleCount += RulesMatching(mDocSheets, aPresContext, aContent, aParentFrame, rules);
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aContent, aParentFrame, rules);
|
||||||
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aContent, aParentFrame, rules);
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aContent, aParentFrame, rules);
|
||||||
|
|
||||||
// then check for cached ruleSet to context or create
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
ContextKey tempKey(parentContext, rules);
|
|
||||||
result = (nsIStyleContext*)mStyleContexts.Get(&tempKey);
|
NS_RELEASE(rules);
|
||||||
if (nsnull == result) {
|
}
|
||||||
if (NS_OK == NS_NewStyleContext(&result, rules, aPresContext, aContent, aParentFrame)) {
|
|
||||||
tempKey.SetContext(result);
|
NS_IF_RELEASE(parentContext);
|
||||||
mStyleContexts.Put(&tempKey, result); // hashtable clones key, so this is OK (table gets first ref)
|
|
||||||
NS_ADDREF(result); // add ref for the caller
|
return result;
|
||||||
//fprintf(stdout, "+");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
PRInt32 StyleSetImpl::RulesMatching(nsISupportsArray* aSheets,
|
||||||
|
nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame,
|
||||||
|
nsISupportsArray* aResults)
|
||||||
|
{
|
||||||
|
PRInt32 ruleCount = 0;
|
||||||
|
|
||||||
|
if (nsnull != aSheets) {
|
||||||
|
PRInt32 sheetCount = aSheets->Count();
|
||||||
|
PRInt32 index;
|
||||||
|
for (index = 0; index < sheetCount; index++) {
|
||||||
|
nsIStyleSheet* sheet = (nsIStyleSheet*)aSheets->ElementAt(index);
|
||||||
|
ruleCount += sheet->RulesMatching(aPresContext, aPseudoTag, aParentFrame,
|
||||||
|
aResults);
|
||||||
|
NS_RELEASE(sheet);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
NS_ADDREF(result);
|
return ruleCount;
|
||||||
//fprintf(stdout, "-");
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame)
|
||||||
|
{
|
||||||
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
|
|
||||||
|
if (nsnull != aParentFrame) {
|
||||||
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
NS_ASSERTION(nsnull != parentContext, "parent must have style context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// want to check parent frame's context for cached child context first
|
||||||
|
|
||||||
|
// then do a brute force rule search
|
||||||
|
|
||||||
|
nsISupportsArray* rules = nsnull;
|
||||||
|
if (NS_OK == NS_NewISupportsArray(&rules)) {
|
||||||
|
PRInt32 ruleCount = RulesMatching(mOverrideSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
|
||||||
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
|
|
||||||
|
NS_RELEASE(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IF_RELEASE(parentContext);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame)
|
||||||
|
{
|
||||||
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
|
|
||||||
|
if (nsnull != aParentFrame) {
|
||||||
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
NS_ASSERTION(nsnull != parentContext, "parent must have style context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// want to check parent frame's context for cached child context first
|
||||||
|
|
||||||
|
// then do a brute force rule search
|
||||||
|
|
||||||
|
nsISupportsArray* rules = nsnull;
|
||||||
|
if (NS_OK == NS_NewISupportsArray(&rules)) {
|
||||||
|
PRInt32 ruleCount = RulesMatching(mOverrideSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
|
||||||
|
if (0 < ruleCount) {
|
||||||
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_RELEASE(rules);
|
NS_RELEASE(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,6 +622,135 @@ void StyleSetImpl::List(FILE* out, PRInt32 aIndent)
|
||||||
List(out, aIndent, mBackstopSheets);
|
List(out, aIndent, mBackstopSheets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ContextNode {
|
||||||
|
nsIStyleContext* mContext;
|
||||||
|
ContextNode* mNext;
|
||||||
|
ContextNode* mChild;
|
||||||
|
ContextNode(nsIStyleContext* aContext)
|
||||||
|
{
|
||||||
|
mContext = aContext;
|
||||||
|
mNext = nsnull;
|
||||||
|
mChild = nsnull;
|
||||||
|
}
|
||||||
|
~ContextNode(void)
|
||||||
|
{
|
||||||
|
if (nsnull != mNext) {
|
||||||
|
delete mNext;
|
||||||
|
}
|
||||||
|
if (nsnull != mChild) {
|
||||||
|
delete mChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ContextNode* gRootNode;
|
||||||
|
|
||||||
|
static ContextNode* FindNode(nsIStyleContext* aContext, ContextNode* aStart)
|
||||||
|
{
|
||||||
|
ContextNode* node = aStart;
|
||||||
|
while (nsnull != node) {
|
||||||
|
if (node->mContext == aContext) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (nsnull != node->mChild) {
|
||||||
|
ContextNode* result = FindNode(aContext, node->mChild);
|
||||||
|
if (nsnull != result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GatherContexts(nsHashKey *aKey, void *aData)
|
||||||
|
{
|
||||||
|
PRBool result = PR_TRUE;
|
||||||
|
|
||||||
|
nsIStyleContext* context = (nsIStyleContext*)aData;
|
||||||
|
nsIStyleContext* parent = context->GetParent();
|
||||||
|
ContextNode* node = new ContextNode(context);
|
||||||
|
|
||||||
|
if (nsnull == gRootNode) {
|
||||||
|
gRootNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nsnull == parent) { // found real root, replace temp
|
||||||
|
node->mNext = gRootNode; // orphan the old root
|
||||||
|
gRootNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ContextNode* parentNode = FindNode(parent, gRootNode);
|
||||||
|
if (nsnull == parentNode) { // hang orhpans off root
|
||||||
|
node->mNext = gRootNode->mNext;
|
||||||
|
gRootNode->mNext = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node->mNext = parentNode->mChild;
|
||||||
|
parentNode->mChild = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// graft orphans
|
||||||
|
ContextNode* prevOrphan = nsnull;
|
||||||
|
ContextNode* orphan = gRootNode;
|
||||||
|
while (nsnull != orphan) {
|
||||||
|
nsIStyleContext* orphanParent = orphan->mContext->GetParent();
|
||||||
|
if (orphanParent == context) { // found our child
|
||||||
|
if (orphan == gRootNode) {
|
||||||
|
gRootNode = orphan->mNext;
|
||||||
|
orphan->mNext = node->mChild;
|
||||||
|
node->mChild = orphan;
|
||||||
|
orphan = gRootNode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ContextNode* foundling = orphan;
|
||||||
|
orphan = orphan->mNext;
|
||||||
|
prevOrphan->mNext = orphan;
|
||||||
|
foundling->mNext = node->mChild;
|
||||||
|
node->mChild = foundling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prevOrphan = orphan;
|
||||||
|
orphan = orphan->mNext;
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(orphanParent);
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(parent);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRInt32 ListNode(ContextNode* aNode, FILE* out, PRInt32 aIndent)
|
||||||
|
{
|
||||||
|
PRInt32 count = 0;
|
||||||
|
ContextNode* node = aNode;
|
||||||
|
while (nsnull != node) {
|
||||||
|
node->mContext->List(out, aIndent);
|
||||||
|
count++;
|
||||||
|
if (nsnull != node->mChild) {
|
||||||
|
nsIStyleContext* childParent = node->mChild->mContext->GetParent();
|
||||||
|
NS_ASSERTION(childParent == node->mContext, "broken graph");
|
||||||
|
NS_RELEASE(childParent);
|
||||||
|
count += ListNode(node->mChild, out, aIndent + 1);
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyleSetImpl::ListContexts(FILE* out, PRInt32 aIndent)
|
||||||
|
{
|
||||||
|
mStyleContexts.Enumerate(GatherContexts);
|
||||||
|
NS_ASSERTION(gRootNode->mNext == nsnull, "dangling orphan");
|
||||||
|
|
||||||
|
PRInt32 listCount = ListNode(gRootNode, out, aIndent);
|
||||||
|
NS_ASSERTION(listCount == mStyleContexts.Count(), "graph incomplete");
|
||||||
|
|
||||||
|
delete gRootNode;
|
||||||
|
gRootNode = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_LAYOUT nsresult
|
NS_LAYOUT nsresult
|
||||||
NS_NewStyleSet(nsIStyleSet** aInstancePtrResult)
|
NS_NewStyleSet(nsIStyleSet** aInstancePtrResult)
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
|
|
||||||
|
|
||||||
static NS_DEFINE_IID(kIStyleSetIID, NS_ISTYLE_SET_IID);
|
static NS_DEFINE_IID(kIStyleSetIID, NS_ISTYLE_SET_IID);
|
||||||
|
|
||||||
class ContextKey : public nsHashKey {
|
class ContextKey : public nsHashKey {
|
||||||
|
@ -196,6 +195,14 @@ public:
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame);
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
|
virtual nsIStyleContext* ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
|
virtual nsIStyleContext* ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame);
|
||||||
|
|
||||||
// xxx style rules enumeration
|
// xxx style rules enumeration
|
||||||
|
|
||||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0);
|
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0);
|
||||||
|
@ -208,12 +215,20 @@ private:
|
||||||
protected:
|
protected:
|
||||||
virtual ~StyleSetImpl();
|
virtual ~StyleSetImpl();
|
||||||
PRBool EnsureArray(nsISupportsArray** aArray);
|
PRBool EnsureArray(nsISupportsArray** aArray);
|
||||||
|
nsIStyleContext* GetContext(nsIPresContext* aPresContext, nsIFrame* aParentFrame,
|
||||||
|
nsIStyleContext* aParentContext, nsISupportsArray* aRules);
|
||||||
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
||||||
nsIPresContext* aPresContext,
|
nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame,
|
nsIFrame* aParentFrame,
|
||||||
nsISupportsArray* aResults);
|
nsISupportsArray* aResults);
|
||||||
|
PRInt32 RulesMatching(nsISupportsArray* aSheets,
|
||||||
|
nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame,
|
||||||
|
nsISupportsArray* aResults);
|
||||||
void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets);
|
void List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets);
|
||||||
|
void ListContexts(FILE* out, PRInt32 aIndent);
|
||||||
|
|
||||||
nsISupportsArray* mOverrideSheets;
|
nsISupportsArray* mOverrideSheets;
|
||||||
nsISupportsArray* mDocSheets;
|
nsISupportsArray* mDocSheets;
|
||||||
|
@ -445,13 +460,33 @@ PRInt32 StyleSetImpl::RulesMatching(nsISupportsArray* aSheets,
|
||||||
return ruleCount;
|
return ruleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::GetContext(nsIPresContext* aPresContext, nsIFrame* aParentFrame,
|
||||||
|
nsIStyleContext* aParentContext, nsISupportsArray* aRules)
|
||||||
|
{
|
||||||
|
// check for cached ruleSet to context or create
|
||||||
|
ContextKey tempKey(aParentContext, aRules);
|
||||||
|
nsIStyleContext* result = (nsIStyleContext*)mStyleContexts.Get(&tempKey);
|
||||||
|
if (nsnull == result) {
|
||||||
|
if (NS_OK == NS_NewStyleContext(&result, aRules, aPresContext, aParentFrame)) {
|
||||||
|
tempKey.SetContext(result);
|
||||||
|
mStyleContexts.Put(&tempKey, result); // hashtable clones key, so this is OK (table gets first ref)
|
||||||
|
NS_ADDREF(result); // add ref for the caller
|
||||||
|
//fprintf(stdout, "+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_ADDREF(result);
|
||||||
|
//fprintf(stdout, "-");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
nsIFrame* aParentFrame)
|
nsIFrame* aParentFrame)
|
||||||
{
|
{
|
||||||
nsIStyleContext* result = nsnull;
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
nsIStyleContext* parentContext = nsnull;
|
|
||||||
|
|
||||||
if (nsnull != aParentFrame) {
|
if (nsnull != aParentFrame) {
|
||||||
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
@ -468,21 +503,96 @@ nsIStyleContext* StyleSetImpl::ResolveStyleFor(nsIPresContext* aPresContext,
|
||||||
ruleCount += RulesMatching(mDocSheets, aPresContext, aContent, aParentFrame, rules);
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aContent, aParentFrame, rules);
|
||||||
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aContent, aParentFrame, rules);
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aContent, aParentFrame, rules);
|
||||||
|
|
||||||
// then check for cached ruleSet to context or create
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
ContextKey tempKey(parentContext, rules);
|
|
||||||
result = (nsIStyleContext*)mStyleContexts.Get(&tempKey);
|
NS_RELEASE(rules);
|
||||||
if (nsnull == result) {
|
}
|
||||||
if (NS_OK == NS_NewStyleContext(&result, rules, aPresContext, aContent, aParentFrame)) {
|
|
||||||
tempKey.SetContext(result);
|
NS_IF_RELEASE(parentContext);
|
||||||
mStyleContexts.Put(&tempKey, result); // hashtable clones key, so this is OK (table gets first ref)
|
|
||||||
NS_ADDREF(result); // add ref for the caller
|
return result;
|
||||||
//fprintf(stdout, "+");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
PRInt32 StyleSetImpl::RulesMatching(nsISupportsArray* aSheets,
|
||||||
|
nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame,
|
||||||
|
nsISupportsArray* aResults)
|
||||||
|
{
|
||||||
|
PRInt32 ruleCount = 0;
|
||||||
|
|
||||||
|
if (nsnull != aSheets) {
|
||||||
|
PRInt32 sheetCount = aSheets->Count();
|
||||||
|
PRInt32 index;
|
||||||
|
for (index = 0; index < sheetCount; index++) {
|
||||||
|
nsIStyleSheet* sheet = (nsIStyleSheet*)aSheets->ElementAt(index);
|
||||||
|
ruleCount += sheet->RulesMatching(aPresContext, aPseudoTag, aParentFrame,
|
||||||
|
aResults);
|
||||||
|
NS_RELEASE(sheet);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
NS_ADDREF(result);
|
return ruleCount;
|
||||||
//fprintf(stdout, "-");
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame)
|
||||||
|
{
|
||||||
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
|
|
||||||
|
if (nsnull != aParentFrame) {
|
||||||
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
NS_ASSERTION(nsnull != parentContext, "parent must have style context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// want to check parent frame's context for cached child context first
|
||||||
|
|
||||||
|
// then do a brute force rule search
|
||||||
|
|
||||||
|
nsISupportsArray* rules = nsnull;
|
||||||
|
if (NS_OK == NS_NewISupportsArray(&rules)) {
|
||||||
|
PRInt32 ruleCount = RulesMatching(mOverrideSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
|
||||||
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
|
|
||||||
|
NS_RELEASE(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IF_RELEASE(parentContext);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||||
|
nsIAtom* aPseudoTag,
|
||||||
|
nsIFrame* aParentFrame)
|
||||||
|
{
|
||||||
|
nsIStyleContext* result = nsnull;
|
||||||
|
nsIStyleContext* parentContext = nsnull;
|
||||||
|
|
||||||
|
if (nsnull != aParentFrame) {
|
||||||
|
aParentFrame->GetStyleContext(aPresContext, parentContext);
|
||||||
|
NS_ASSERTION(nsnull != parentContext, "parent must have style context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// want to check parent frame's context for cached child context first
|
||||||
|
|
||||||
|
// then do a brute force rule search
|
||||||
|
|
||||||
|
nsISupportsArray* rules = nsnull;
|
||||||
|
if (NS_OK == NS_NewISupportsArray(&rules)) {
|
||||||
|
PRInt32 ruleCount = RulesMatching(mOverrideSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mDocSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
ruleCount += RulesMatching(mBackstopSheets, aPresContext, aPseudoTag, aParentFrame, rules);
|
||||||
|
|
||||||
|
if (0 < ruleCount) {
|
||||||
|
result = GetContext(aPresContext, aParentFrame, parentContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_RELEASE(rules);
|
NS_RELEASE(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,6 +622,135 @@ void StyleSetImpl::List(FILE* out, PRInt32 aIndent)
|
||||||
List(out, aIndent, mBackstopSheets);
|
List(out, aIndent, mBackstopSheets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ContextNode {
|
||||||
|
nsIStyleContext* mContext;
|
||||||
|
ContextNode* mNext;
|
||||||
|
ContextNode* mChild;
|
||||||
|
ContextNode(nsIStyleContext* aContext)
|
||||||
|
{
|
||||||
|
mContext = aContext;
|
||||||
|
mNext = nsnull;
|
||||||
|
mChild = nsnull;
|
||||||
|
}
|
||||||
|
~ContextNode(void)
|
||||||
|
{
|
||||||
|
if (nsnull != mNext) {
|
||||||
|
delete mNext;
|
||||||
|
}
|
||||||
|
if (nsnull != mChild) {
|
||||||
|
delete mChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ContextNode* gRootNode;
|
||||||
|
|
||||||
|
static ContextNode* FindNode(nsIStyleContext* aContext, ContextNode* aStart)
|
||||||
|
{
|
||||||
|
ContextNode* node = aStart;
|
||||||
|
while (nsnull != node) {
|
||||||
|
if (node->mContext == aContext) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (nsnull != node->mChild) {
|
||||||
|
ContextNode* result = FindNode(aContext, node->mChild);
|
||||||
|
if (nsnull != result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GatherContexts(nsHashKey *aKey, void *aData)
|
||||||
|
{
|
||||||
|
PRBool result = PR_TRUE;
|
||||||
|
|
||||||
|
nsIStyleContext* context = (nsIStyleContext*)aData;
|
||||||
|
nsIStyleContext* parent = context->GetParent();
|
||||||
|
ContextNode* node = new ContextNode(context);
|
||||||
|
|
||||||
|
if (nsnull == gRootNode) {
|
||||||
|
gRootNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nsnull == parent) { // found real root, replace temp
|
||||||
|
node->mNext = gRootNode; // orphan the old root
|
||||||
|
gRootNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ContextNode* parentNode = FindNode(parent, gRootNode);
|
||||||
|
if (nsnull == parentNode) { // hang orhpans off root
|
||||||
|
node->mNext = gRootNode->mNext;
|
||||||
|
gRootNode->mNext = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node->mNext = parentNode->mChild;
|
||||||
|
parentNode->mChild = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// graft orphans
|
||||||
|
ContextNode* prevOrphan = nsnull;
|
||||||
|
ContextNode* orphan = gRootNode;
|
||||||
|
while (nsnull != orphan) {
|
||||||
|
nsIStyleContext* orphanParent = orphan->mContext->GetParent();
|
||||||
|
if (orphanParent == context) { // found our child
|
||||||
|
if (orphan == gRootNode) {
|
||||||
|
gRootNode = orphan->mNext;
|
||||||
|
orphan->mNext = node->mChild;
|
||||||
|
node->mChild = orphan;
|
||||||
|
orphan = gRootNode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ContextNode* foundling = orphan;
|
||||||
|
orphan = orphan->mNext;
|
||||||
|
prevOrphan->mNext = orphan;
|
||||||
|
foundling->mNext = node->mChild;
|
||||||
|
node->mChild = foundling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prevOrphan = orphan;
|
||||||
|
orphan = orphan->mNext;
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(orphanParent);
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(parent);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRInt32 ListNode(ContextNode* aNode, FILE* out, PRInt32 aIndent)
|
||||||
|
{
|
||||||
|
PRInt32 count = 0;
|
||||||
|
ContextNode* node = aNode;
|
||||||
|
while (nsnull != node) {
|
||||||
|
node->mContext->List(out, aIndent);
|
||||||
|
count++;
|
||||||
|
if (nsnull != node->mChild) {
|
||||||
|
nsIStyleContext* childParent = node->mChild->mContext->GetParent();
|
||||||
|
NS_ASSERTION(childParent == node->mContext, "broken graph");
|
||||||
|
NS_RELEASE(childParent);
|
||||||
|
count += ListNode(node->mChild, out, aIndent + 1);
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyleSetImpl::ListContexts(FILE* out, PRInt32 aIndent)
|
||||||
|
{
|
||||||
|
mStyleContexts.Enumerate(GatherContexts);
|
||||||
|
NS_ASSERTION(gRootNode->mNext == nsnull, "dangling orphan");
|
||||||
|
|
||||||
|
PRInt32 listCount = ListNode(gRootNode, out, aIndent);
|
||||||
|
NS_ASSERTION(listCount == mStyleContexts.Count(), "graph incomplete");
|
||||||
|
|
||||||
|
delete gRootNode;
|
||||||
|
gRootNode = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_LAYOUT nsresult
|
NS_LAYOUT nsresult
|
||||||
NS_NewStyleSet(nsIStyleSet** aInstancePtrResult)
|
NS_NewStyleSet(nsIStyleSet** aInstancePtrResult)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче