зеркало из https://github.com/mozilla/pjs.git
added multimap to track content that didn't get a frame
Fix for bug 9013 (and any dynamic change from display:none) r=troy
This commit is contained in:
Родитель
697873d57e
Коммит
95550bd4b8
|
@ -74,6 +74,55 @@ protected:
|
||||||
PLHashTable* mTable;
|
PLHashTable* mTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UndisplayedNode {
|
||||||
|
UndisplayedNode(nsIContent* aContent, nsIStyleContext* aStyle)
|
||||||
|
{
|
||||||
|
mContent = aContent;
|
||||||
|
mStyle = aStyle;
|
||||||
|
NS_ADDREF(mStyle);
|
||||||
|
mNext = nsnull;
|
||||||
|
}
|
||||||
|
UndisplayedNode(nsIStyleContext* aPseudoStyle)
|
||||||
|
{
|
||||||
|
mContent = nsnull;
|
||||||
|
mStyle = aPseudoStyle;
|
||||||
|
NS_ADDREF(mStyle);
|
||||||
|
mNext = nsnull;
|
||||||
|
}
|
||||||
|
~UndisplayedNode(void)
|
||||||
|
{
|
||||||
|
NS_RELEASE(mStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIContent* mContent;
|
||||||
|
nsIStyleContext* mStyle;
|
||||||
|
UndisplayedNode* mNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UndisplayedMap {
|
||||||
|
public:
|
||||||
|
UndisplayedMap(PRUint32 aNumBuckets = 16);
|
||||||
|
~UndisplayedMap(void);
|
||||||
|
|
||||||
|
UndisplayedNode* GetFirstNode(nsIContent* aParentContent);
|
||||||
|
|
||||||
|
nsresult AddNodeFor(nsIContent* aParentContent, nsIContent* aChild, nsIStyleContext* aStyle);
|
||||||
|
nsresult AddNodeFor(nsIContent* aParentContent, nsIStyleContext* aPseudoStyle);
|
||||||
|
|
||||||
|
nsresult RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode);
|
||||||
|
nsresult RemoveNodesFor(nsIContent* aParentContent);
|
||||||
|
|
||||||
|
// Removes all entries from the hash table
|
||||||
|
void Clear(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PLHashEntry** GetEntryFor(nsIContent* aParentContent);
|
||||||
|
nsresult AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent);
|
||||||
|
|
||||||
|
PLHashTable* mTable;
|
||||||
|
PLHashEntry** mLastLookup;
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
class FrameManager;
|
class FrameManager;
|
||||||
|
@ -112,6 +161,14 @@ public:
|
||||||
nsIFrame* aPlaceholderFrame);
|
nsIFrame* aPlaceholderFrame);
|
||||||
NS_IMETHOD ClearPlaceholderFrameMap();
|
NS_IMETHOD ClearPlaceholderFrameMap();
|
||||||
|
|
||||||
|
// Undisplayed content functions
|
||||||
|
NS_IMETHOD SetUndisplayedContent(nsIContent* aContent, nsIStyleContext* aStyleContext);
|
||||||
|
NS_IMETHOD SetUndisplayedPseudoIn(nsIStyleContext* aPseudoContext,
|
||||||
|
nsIContent* aParentContent);
|
||||||
|
NS_IMETHOD ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent);
|
||||||
|
NS_IMETHOD ClearAllUndisplayedContentIn(nsIContent* aParentContent);
|
||||||
|
NS_IMETHOD ClearUndisplayedContentMap();
|
||||||
|
|
||||||
// Functions for manipulating the frame model
|
// Functions for manipulating the frame model
|
||||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||||
nsIPresShell& aPresShell,
|
nsIPresShell& aPresShell,
|
||||||
|
@ -162,8 +219,10 @@ private:
|
||||||
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
||||||
nsDST* mPrimaryFrameMap;
|
nsDST* mPrimaryFrameMap;
|
||||||
FrameHashTable* mPlaceholderMap;
|
FrameHashTable* mPlaceholderMap;
|
||||||
|
UndisplayedMap* mUndisplayedMap;
|
||||||
CantRenderReplacedElementEvent* mPostedEvents;
|
CantRenderReplacedElementEvent* mPostedEvents;
|
||||||
|
|
||||||
|
|
||||||
void ReResolveStyleContext(nsIPresContext& aPresContext,
|
void ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsIStyleContext* aParentContext,
|
nsIStyleContext* aParentContext,
|
||||||
|
@ -211,6 +270,7 @@ FrameManager::~FrameManager()
|
||||||
|
|
||||||
delete mPrimaryFrameMap;
|
delete mPrimaryFrameMap;
|
||||||
delete mPlaceholderMap;
|
delete mPlaceholderMap;
|
||||||
|
delete mUndisplayedMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -366,6 +426,74 @@ FrameManager::ClearPlaceholderFrameMap()
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::SetUndisplayedContent(nsIContent* aContent,
|
||||||
|
nsIStyleContext* aStyleContext)
|
||||||
|
{
|
||||||
|
if (! mUndisplayedMap) {
|
||||||
|
mUndisplayedMap = new UndisplayedMap;
|
||||||
|
}
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
nsresult result = NS_OK;
|
||||||
|
nsIContent* parent = nsnull;
|
||||||
|
aContent->GetParent(parent);
|
||||||
|
if (parent) {
|
||||||
|
result = mUndisplayedMap->AddNodeFor(parent, aContent, aStyleContext);
|
||||||
|
NS_RELEASE(parent);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::SetUndisplayedPseudoIn(nsIStyleContext* aPseudoContext,
|
||||||
|
nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (! mUndisplayedMap) {
|
||||||
|
mUndisplayedMap = new UndisplayedMap;
|
||||||
|
}
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
return mUndisplayedMap->AddNodeFor(aParentContent, aPseudoContext);
|
||||||
|
}
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aParentContent);
|
||||||
|
while (node) {
|
||||||
|
if (node->mContent == aContent) {
|
||||||
|
return mUndisplayedMap->RemoveNodeFor(aParentContent, node);
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
return mUndisplayedMap->RemoveNodesFor(aParentContent);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::ClearUndisplayedContentMap()
|
||||||
|
{
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
mUndisplayedMap->Clear();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
FrameManager::AppendFrames(nsIPresContext& aPresContext,
|
FrameManager::AppendFrames(nsIPresContext& aPresContext,
|
||||||
nsIPresShell& aPresShell,
|
nsIPresShell& aPresShell,
|
||||||
|
@ -842,13 +970,13 @@ FrameManager::ReParentStyleContext(nsIPresContext& aPresContext,
|
||||||
|
|
||||||
static PRInt32
|
static PRInt32
|
||||||
CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext,
|
CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext,
|
||||||
nsIFrame* aFrame, nsStyleChangeList& aChangeList,
|
nsIFrame* aFrame, nsIContent* aContent,
|
||||||
PRInt32 aMinChange)
|
nsStyleChangeList& aChangeList, PRInt32 aMinChange)
|
||||||
{
|
{
|
||||||
PRInt32 ourChange = NS_STYLE_HINT_NONE;
|
PRInt32 ourChange = NS_STYLE_HINT_NONE;
|
||||||
aNewContext->CalcStyleDifference(aOldContext, ourChange);
|
aNewContext->CalcStyleDifference(aOldContext, ourChange);
|
||||||
if (aMinChange < ourChange) {
|
if (aMinChange < ourChange) {
|
||||||
aChangeList.AppendChange(aFrame, ourChange);
|
aChangeList.AppendChange(aFrame, aContent, ourChange);
|
||||||
aMinChange = ourChange;
|
aMinChange = ourChange;
|
||||||
}
|
}
|
||||||
return aMinChange;
|
return aMinChange;
|
||||||
|
@ -892,7 +1020,7 @@ FrameManager::ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
NS_ASSERTION(newContext, "failed to get new style context");
|
NS_ASSERTION(newContext, "failed to get new style context");
|
||||||
if (newContext) {
|
if (newContext) {
|
||||||
if (newContext != oldContext) {
|
if (newContext != oldContext) {
|
||||||
aMinChange = CaptureChange(oldContext, newContext, aFrame, aChangeList, aMinChange);
|
aMinChange = CaptureChange(oldContext, newContext, aFrame, content, aChangeList, aMinChange);
|
||||||
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) { // if frame gets regenerated, let it keep old context
|
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) { // if frame gets regenerated, let it keep old context
|
||||||
aFrame->SetStyleContext(&aPresContext, newContext);
|
aFrame->SetStyleContext(&aPresContext, newContext);
|
||||||
}
|
}
|
||||||
|
@ -923,11 +1051,14 @@ FrameManager::ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
if (NS_SUCCEEDED(result) && newExtraContext) {
|
if (NS_SUCCEEDED(result) && newExtraContext) {
|
||||||
if (oldExtraContext != newExtraContext) {
|
if (oldExtraContext != newExtraContext) {
|
||||||
aMinChange = CaptureChange(oldExtraContext, newExtraContext, aFrame,
|
aMinChange = CaptureChange(oldExtraContext, newExtraContext, aFrame,
|
||||||
aChangeList, aMinChange);
|
content, aChangeList, aMinChange);
|
||||||
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) {
|
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) {
|
||||||
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
oldExtraContext->RemapStyle(&aPresContext, PR_FALSE);
|
||||||
|
}
|
||||||
NS_RELEASE(newExtraContext);
|
NS_RELEASE(newExtraContext);
|
||||||
}
|
}
|
||||||
NS_RELEASE(oldExtraContext);
|
NS_RELEASE(oldExtraContext);
|
||||||
|
@ -938,6 +1069,38 @@ FrameManager::ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now look for undisplayed child content and pseudos
|
||||||
|
if (localContent) {
|
||||||
|
UndisplayedNode* undisplayed = mUndisplayedMap->GetFirstNode(localContent);
|
||||||
|
while (undisplayed) {
|
||||||
|
nsIStyleContext* undisplayedContext = nsnull;
|
||||||
|
if (undisplayed->mContent) { // child content
|
||||||
|
aPresContext.ResolveStyleContextFor(undisplayed->mContent, newContext,
|
||||||
|
PR_FALSE, &undisplayedContext);
|
||||||
|
}
|
||||||
|
else { // pseudo element
|
||||||
|
undisplayed->mStyle->GetPseudoType(pseudoTag);
|
||||||
|
NS_ASSERTION(pseudoTag, "pseudo element without tag");
|
||||||
|
aPresContext.ResolvePseudoStyleContextFor(localContent, pseudoTag, newContext, PR_FALSE,
|
||||||
|
&undisplayedContext);
|
||||||
|
NS_RELEASE(pseudoTag);
|
||||||
|
}
|
||||||
|
if (undisplayedContext) {
|
||||||
|
if (undisplayedContext == undisplayed->mStyle) {
|
||||||
|
undisplayedContext->RemapStyle(&aPresContext);
|
||||||
|
}
|
||||||
|
const nsStyleDisplay* display =
|
||||||
|
(const nsStyleDisplay*)undisplayedContext->GetStyleData(eStyleStruct_Display);
|
||||||
|
if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
|
||||||
|
aChangeList.AppendChange(nsnull, ((undisplayed->mContent) ? undisplayed->mContent : localContent),
|
||||||
|
NS_STYLE_HINT_FRAMECHANGE);
|
||||||
|
}
|
||||||
|
NS_RELEASE(undisplayedContext);
|
||||||
|
}
|
||||||
|
undisplayed = undisplayed->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
aResultChange = aMinChange;
|
aResultChange = aMinChange;
|
||||||
|
|
||||||
// now do children
|
// now do children
|
||||||
|
@ -1229,3 +1392,148 @@ FrameHashTable::Dump(FILE* fp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
UndisplayedMap::UndisplayedMap(PRUint32 aNumBuckets)
|
||||||
|
{
|
||||||
|
mTable = PL_NewHashTable(aNumBuckets, (PLHashFunction)HashKey,
|
||||||
|
(PLHashComparator)CompareKeys,
|
||||||
|
(PLHashComparator)nsnull,
|
||||||
|
nsnull, nsnull);
|
||||||
|
mLastLookup = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndisplayedMap::~UndisplayedMap(void)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
PL_HashTableDestroy(mTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLHashEntry**
|
||||||
|
UndisplayedMap::GetEntryFor(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (mLastLookup && (aParentContent == (*mLastLookup)->key)) {
|
||||||
|
return mLastLookup;
|
||||||
|
}
|
||||||
|
PLHashNumber hashCode = (PLHashNumber)(void*)aParentContent;
|
||||||
|
PLHashEntry** entry = PL_HashTableRawLookup(mTable, hashCode, aParentContent);
|
||||||
|
if (*entry) {
|
||||||
|
mLastLookup = entry;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndisplayedNode*
|
||||||
|
UndisplayedMap::GetFirstNode(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
if (*entry) {
|
||||||
|
return (UndisplayedNode*)((*entry)->value);
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
if (*entry) {
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
||||||
|
while (node->mNext) {
|
||||||
|
NS_ASSERTION((node->mContent != aNode->mContent) ||
|
||||||
|
((node->mContent == nsnull) &&
|
||||||
|
(node->mStyle != aNode->mStyle)), "node in map twice");
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
node->mNext = aNode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PLHashNumber hashCode = (PLHashNumber)(void*)aParentContent;
|
||||||
|
PL_HashTableRawAdd(mTable, entry, hashCode, aParentContent, aNode);
|
||||||
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::AddNodeFor(nsIContent* aParentContent, nsIContent* aChild,
|
||||||
|
nsIStyleContext* aStyle)
|
||||||
|
{
|
||||||
|
UndisplayedNode* node = new UndisplayedNode(aChild, aStyle);
|
||||||
|
if (! node) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
return AppendNodeFor(node, aParentContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::AddNodeFor(nsIContent* aParentContent, nsIStyleContext* aPseudoStyle)
|
||||||
|
{
|
||||||
|
UndisplayedNode* node = new UndisplayedNode(aPseudoStyle);
|
||||||
|
if (! node) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
return AppendNodeFor(node, aParentContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
NS_ASSERTION(*entry, "content not in map");
|
||||||
|
if (*entry) {
|
||||||
|
if ((UndisplayedNode*)((*entry)->value) == aNode) { // first node
|
||||||
|
if (aNode->mNext) {
|
||||||
|
(*entry)->value = aNode->mNext;
|
||||||
|
aNode->mNext = nsnull;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PL_HashTableRawRemove(mTable, entry, *entry);
|
||||||
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
||||||
|
while (node->mNext) {
|
||||||
|
if (node->mNext == aNode) {
|
||||||
|
node->mNext = aNode->mNext;
|
||||||
|
aNode->mNext = nsnull;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete aNode;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
NS_ASSERTION(entry, "content not in map");
|
||||||
|
if (*entry) {
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
||||||
|
delete node;
|
||||||
|
if (entry == mLastLookup) {
|
||||||
|
mLastLookup = nsnull;
|
||||||
|
}
|
||||||
|
PL_HashTableRawRemove(mTable, entry, *entry);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRIntn
|
||||||
|
RemoveUndisplayedEntry(PLHashEntry* he, PRIntn i, void* arg)
|
||||||
|
{
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)(he->value);
|
||||||
|
delete node;
|
||||||
|
// Remove and free this entry and continue enumerating
|
||||||
|
return HT_ENUMERATE_REMOVE | HT_ENUMERATE_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UndisplayedMap::Clear(void)
|
||||||
|
{
|
||||||
|
mLastLookup = nsnull;
|
||||||
|
PL_HashTableEnumerateEntries(mTable, RemoveUndisplayedEntry, 0);
|
||||||
|
}
|
||||||
|
|
|
@ -74,6 +74,55 @@ protected:
|
||||||
PLHashTable* mTable;
|
PLHashTable* mTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UndisplayedNode {
|
||||||
|
UndisplayedNode(nsIContent* aContent, nsIStyleContext* aStyle)
|
||||||
|
{
|
||||||
|
mContent = aContent;
|
||||||
|
mStyle = aStyle;
|
||||||
|
NS_ADDREF(mStyle);
|
||||||
|
mNext = nsnull;
|
||||||
|
}
|
||||||
|
UndisplayedNode(nsIStyleContext* aPseudoStyle)
|
||||||
|
{
|
||||||
|
mContent = nsnull;
|
||||||
|
mStyle = aPseudoStyle;
|
||||||
|
NS_ADDREF(mStyle);
|
||||||
|
mNext = nsnull;
|
||||||
|
}
|
||||||
|
~UndisplayedNode(void)
|
||||||
|
{
|
||||||
|
NS_RELEASE(mStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIContent* mContent;
|
||||||
|
nsIStyleContext* mStyle;
|
||||||
|
UndisplayedNode* mNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UndisplayedMap {
|
||||||
|
public:
|
||||||
|
UndisplayedMap(PRUint32 aNumBuckets = 16);
|
||||||
|
~UndisplayedMap(void);
|
||||||
|
|
||||||
|
UndisplayedNode* GetFirstNode(nsIContent* aParentContent);
|
||||||
|
|
||||||
|
nsresult AddNodeFor(nsIContent* aParentContent, nsIContent* aChild, nsIStyleContext* aStyle);
|
||||||
|
nsresult AddNodeFor(nsIContent* aParentContent, nsIStyleContext* aPseudoStyle);
|
||||||
|
|
||||||
|
nsresult RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode);
|
||||||
|
nsresult RemoveNodesFor(nsIContent* aParentContent);
|
||||||
|
|
||||||
|
// Removes all entries from the hash table
|
||||||
|
void Clear(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PLHashEntry** GetEntryFor(nsIContent* aParentContent);
|
||||||
|
nsresult AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent);
|
||||||
|
|
||||||
|
PLHashTable* mTable;
|
||||||
|
PLHashEntry** mLastLookup;
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
class FrameManager;
|
class FrameManager;
|
||||||
|
@ -112,6 +161,14 @@ public:
|
||||||
nsIFrame* aPlaceholderFrame);
|
nsIFrame* aPlaceholderFrame);
|
||||||
NS_IMETHOD ClearPlaceholderFrameMap();
|
NS_IMETHOD ClearPlaceholderFrameMap();
|
||||||
|
|
||||||
|
// Undisplayed content functions
|
||||||
|
NS_IMETHOD SetUndisplayedContent(nsIContent* aContent, nsIStyleContext* aStyleContext);
|
||||||
|
NS_IMETHOD SetUndisplayedPseudoIn(nsIStyleContext* aPseudoContext,
|
||||||
|
nsIContent* aParentContent);
|
||||||
|
NS_IMETHOD ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent);
|
||||||
|
NS_IMETHOD ClearAllUndisplayedContentIn(nsIContent* aParentContent);
|
||||||
|
NS_IMETHOD ClearUndisplayedContentMap();
|
||||||
|
|
||||||
// Functions for manipulating the frame model
|
// Functions for manipulating the frame model
|
||||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||||
nsIPresShell& aPresShell,
|
nsIPresShell& aPresShell,
|
||||||
|
@ -162,8 +219,10 @@ private:
|
||||||
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
||||||
nsDST* mPrimaryFrameMap;
|
nsDST* mPrimaryFrameMap;
|
||||||
FrameHashTable* mPlaceholderMap;
|
FrameHashTable* mPlaceholderMap;
|
||||||
|
UndisplayedMap* mUndisplayedMap;
|
||||||
CantRenderReplacedElementEvent* mPostedEvents;
|
CantRenderReplacedElementEvent* mPostedEvents;
|
||||||
|
|
||||||
|
|
||||||
void ReResolveStyleContext(nsIPresContext& aPresContext,
|
void ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsIStyleContext* aParentContext,
|
nsIStyleContext* aParentContext,
|
||||||
|
@ -211,6 +270,7 @@ FrameManager::~FrameManager()
|
||||||
|
|
||||||
delete mPrimaryFrameMap;
|
delete mPrimaryFrameMap;
|
||||||
delete mPlaceholderMap;
|
delete mPlaceholderMap;
|
||||||
|
delete mUndisplayedMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -366,6 +426,74 @@ FrameManager::ClearPlaceholderFrameMap()
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::SetUndisplayedContent(nsIContent* aContent,
|
||||||
|
nsIStyleContext* aStyleContext)
|
||||||
|
{
|
||||||
|
if (! mUndisplayedMap) {
|
||||||
|
mUndisplayedMap = new UndisplayedMap;
|
||||||
|
}
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
nsresult result = NS_OK;
|
||||||
|
nsIContent* parent = nsnull;
|
||||||
|
aContent->GetParent(parent);
|
||||||
|
if (parent) {
|
||||||
|
result = mUndisplayedMap->AddNodeFor(parent, aContent, aStyleContext);
|
||||||
|
NS_RELEASE(parent);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::SetUndisplayedPseudoIn(nsIStyleContext* aPseudoContext,
|
||||||
|
nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (! mUndisplayedMap) {
|
||||||
|
mUndisplayedMap = new UndisplayedMap;
|
||||||
|
}
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
return mUndisplayedMap->AddNodeFor(aParentContent, aPseudoContext);
|
||||||
|
}
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::ClearUndisplayedContentIn(nsIContent* aContent, nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aParentContent);
|
||||||
|
while (node) {
|
||||||
|
if (node->mContent == aContent) {
|
||||||
|
return mUndisplayedMap->RemoveNodeFor(aParentContent, node);
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
return mUndisplayedMap->RemoveNodesFor(aParentContent);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FrameManager::ClearUndisplayedContentMap()
|
||||||
|
{
|
||||||
|
if (mUndisplayedMap) {
|
||||||
|
mUndisplayedMap->Clear();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
FrameManager::AppendFrames(nsIPresContext& aPresContext,
|
FrameManager::AppendFrames(nsIPresContext& aPresContext,
|
||||||
nsIPresShell& aPresShell,
|
nsIPresShell& aPresShell,
|
||||||
|
@ -842,13 +970,13 @@ FrameManager::ReParentStyleContext(nsIPresContext& aPresContext,
|
||||||
|
|
||||||
static PRInt32
|
static PRInt32
|
||||||
CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext,
|
CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext,
|
||||||
nsIFrame* aFrame, nsStyleChangeList& aChangeList,
|
nsIFrame* aFrame, nsIContent* aContent,
|
||||||
PRInt32 aMinChange)
|
nsStyleChangeList& aChangeList, PRInt32 aMinChange)
|
||||||
{
|
{
|
||||||
PRInt32 ourChange = NS_STYLE_HINT_NONE;
|
PRInt32 ourChange = NS_STYLE_HINT_NONE;
|
||||||
aNewContext->CalcStyleDifference(aOldContext, ourChange);
|
aNewContext->CalcStyleDifference(aOldContext, ourChange);
|
||||||
if (aMinChange < ourChange) {
|
if (aMinChange < ourChange) {
|
||||||
aChangeList.AppendChange(aFrame, ourChange);
|
aChangeList.AppendChange(aFrame, aContent, ourChange);
|
||||||
aMinChange = ourChange;
|
aMinChange = ourChange;
|
||||||
}
|
}
|
||||||
return aMinChange;
|
return aMinChange;
|
||||||
|
@ -892,7 +1020,7 @@ FrameManager::ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
NS_ASSERTION(newContext, "failed to get new style context");
|
NS_ASSERTION(newContext, "failed to get new style context");
|
||||||
if (newContext) {
|
if (newContext) {
|
||||||
if (newContext != oldContext) {
|
if (newContext != oldContext) {
|
||||||
aMinChange = CaptureChange(oldContext, newContext, aFrame, aChangeList, aMinChange);
|
aMinChange = CaptureChange(oldContext, newContext, aFrame, content, aChangeList, aMinChange);
|
||||||
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) { // if frame gets regenerated, let it keep old context
|
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) { // if frame gets regenerated, let it keep old context
|
||||||
aFrame->SetStyleContext(&aPresContext, newContext);
|
aFrame->SetStyleContext(&aPresContext, newContext);
|
||||||
}
|
}
|
||||||
|
@ -923,11 +1051,14 @@ FrameManager::ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
if (NS_SUCCEEDED(result) && newExtraContext) {
|
if (NS_SUCCEEDED(result) && newExtraContext) {
|
||||||
if (oldExtraContext != newExtraContext) {
|
if (oldExtraContext != newExtraContext) {
|
||||||
aMinChange = CaptureChange(oldExtraContext, newExtraContext, aFrame,
|
aMinChange = CaptureChange(oldExtraContext, newExtraContext, aFrame,
|
||||||
aChangeList, aMinChange);
|
content, aChangeList, aMinChange);
|
||||||
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) {
|
if (aMinChange < NS_STYLE_HINT_FRAMECHANGE) {
|
||||||
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
oldExtraContext->RemapStyle(&aPresContext, PR_FALSE);
|
||||||
|
}
|
||||||
NS_RELEASE(newExtraContext);
|
NS_RELEASE(newExtraContext);
|
||||||
}
|
}
|
||||||
NS_RELEASE(oldExtraContext);
|
NS_RELEASE(oldExtraContext);
|
||||||
|
@ -938,6 +1069,38 @@ FrameManager::ReResolveStyleContext(nsIPresContext& aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now look for undisplayed child content and pseudos
|
||||||
|
if (localContent) {
|
||||||
|
UndisplayedNode* undisplayed = mUndisplayedMap->GetFirstNode(localContent);
|
||||||
|
while (undisplayed) {
|
||||||
|
nsIStyleContext* undisplayedContext = nsnull;
|
||||||
|
if (undisplayed->mContent) { // child content
|
||||||
|
aPresContext.ResolveStyleContextFor(undisplayed->mContent, newContext,
|
||||||
|
PR_FALSE, &undisplayedContext);
|
||||||
|
}
|
||||||
|
else { // pseudo element
|
||||||
|
undisplayed->mStyle->GetPseudoType(pseudoTag);
|
||||||
|
NS_ASSERTION(pseudoTag, "pseudo element without tag");
|
||||||
|
aPresContext.ResolvePseudoStyleContextFor(localContent, pseudoTag, newContext, PR_FALSE,
|
||||||
|
&undisplayedContext);
|
||||||
|
NS_RELEASE(pseudoTag);
|
||||||
|
}
|
||||||
|
if (undisplayedContext) {
|
||||||
|
if (undisplayedContext == undisplayed->mStyle) {
|
||||||
|
undisplayedContext->RemapStyle(&aPresContext);
|
||||||
|
}
|
||||||
|
const nsStyleDisplay* display =
|
||||||
|
(const nsStyleDisplay*)undisplayedContext->GetStyleData(eStyleStruct_Display);
|
||||||
|
if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
|
||||||
|
aChangeList.AppendChange(nsnull, ((undisplayed->mContent) ? undisplayed->mContent : localContent),
|
||||||
|
NS_STYLE_HINT_FRAMECHANGE);
|
||||||
|
}
|
||||||
|
NS_RELEASE(undisplayedContext);
|
||||||
|
}
|
||||||
|
undisplayed = undisplayed->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
aResultChange = aMinChange;
|
aResultChange = aMinChange;
|
||||||
|
|
||||||
// now do children
|
// now do children
|
||||||
|
@ -1229,3 +1392,148 @@ FrameHashTable::Dump(FILE* fp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
UndisplayedMap::UndisplayedMap(PRUint32 aNumBuckets)
|
||||||
|
{
|
||||||
|
mTable = PL_NewHashTable(aNumBuckets, (PLHashFunction)HashKey,
|
||||||
|
(PLHashComparator)CompareKeys,
|
||||||
|
(PLHashComparator)nsnull,
|
||||||
|
nsnull, nsnull);
|
||||||
|
mLastLookup = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndisplayedMap::~UndisplayedMap(void)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
PL_HashTableDestroy(mTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLHashEntry**
|
||||||
|
UndisplayedMap::GetEntryFor(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
if (mLastLookup && (aParentContent == (*mLastLookup)->key)) {
|
||||||
|
return mLastLookup;
|
||||||
|
}
|
||||||
|
PLHashNumber hashCode = (PLHashNumber)(void*)aParentContent;
|
||||||
|
PLHashEntry** entry = PL_HashTableRawLookup(mTable, hashCode, aParentContent);
|
||||||
|
if (*entry) {
|
||||||
|
mLastLookup = entry;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
UndisplayedNode*
|
||||||
|
UndisplayedMap::GetFirstNode(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
if (*entry) {
|
||||||
|
return (UndisplayedNode*)((*entry)->value);
|
||||||
|
}
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
if (*entry) {
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
||||||
|
while (node->mNext) {
|
||||||
|
NS_ASSERTION((node->mContent != aNode->mContent) ||
|
||||||
|
((node->mContent == nsnull) &&
|
||||||
|
(node->mStyle != aNode->mStyle)), "node in map twice");
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
node->mNext = aNode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PLHashNumber hashCode = (PLHashNumber)(void*)aParentContent;
|
||||||
|
PL_HashTableRawAdd(mTable, entry, hashCode, aParentContent, aNode);
|
||||||
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::AddNodeFor(nsIContent* aParentContent, nsIContent* aChild,
|
||||||
|
nsIStyleContext* aStyle)
|
||||||
|
{
|
||||||
|
UndisplayedNode* node = new UndisplayedNode(aChild, aStyle);
|
||||||
|
if (! node) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
return AppendNodeFor(node, aParentContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::AddNodeFor(nsIContent* aParentContent, nsIStyleContext* aPseudoStyle)
|
||||||
|
{
|
||||||
|
UndisplayedNode* node = new UndisplayedNode(aPseudoStyle);
|
||||||
|
if (! node) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
return AppendNodeFor(node, aParentContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
NS_ASSERTION(*entry, "content not in map");
|
||||||
|
if (*entry) {
|
||||||
|
if ((UndisplayedNode*)((*entry)->value) == aNode) { // first node
|
||||||
|
if (aNode->mNext) {
|
||||||
|
(*entry)->value = aNode->mNext;
|
||||||
|
aNode->mNext = nsnull;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PL_HashTableRawRemove(mTable, entry, *entry);
|
||||||
|
mLastLookup = nsnull; // hashtable may have shifted bucket out from under us
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
||||||
|
while (node->mNext) {
|
||||||
|
if (node->mNext == aNode) {
|
||||||
|
node->mNext = aNode->mNext;
|
||||||
|
aNode->mNext = nsnull;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = node->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete aNode;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent)
|
||||||
|
{
|
||||||
|
PLHashEntry** entry = GetEntryFor(aParentContent);
|
||||||
|
NS_ASSERTION(entry, "content not in map");
|
||||||
|
if (*entry) {
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
|
||||||
|
delete node;
|
||||||
|
if (entry == mLastLookup) {
|
||||||
|
mLastLookup = nsnull;
|
||||||
|
}
|
||||||
|
PL_HashTableRawRemove(mTable, entry, *entry);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRIntn
|
||||||
|
RemoveUndisplayedEntry(PLHashEntry* he, PRIntn i, void* arg)
|
||||||
|
{
|
||||||
|
UndisplayedNode* node = (UndisplayedNode*)(he->value);
|
||||||
|
delete node;
|
||||||
|
// Remove and free this entry and continue enumerating
|
||||||
|
return HT_ENUMERATE_REMOVE | HT_ENUMERATE_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UndisplayedMap::Clear(void)
|
||||||
|
{
|
||||||
|
mLastLookup = nsnull;
|
||||||
|
PL_HashTableEnumerateEntries(mTable, RemoveUndisplayedEntry, 0);
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче