Fix 2 cases where ReResolveStyleContext was broken, causing serious problems with dynamic style reresolution. Change nsIFrame::GetStyleContextProvider to GetParentStyleContextFrame, always use its result rather than using the parent frame in some cases, and move a bit of the complexity into the GetParentStyleContextFrame implementations. Fix block-within-inline case (bug 129350) using a special-previous-sibling frame property and ensuring that NS_FRAME_IS_SPECIAL is copied when frames are split. Fix out-of-flow frame case (bug 88154) by going to the placeholder map and by parenting the placeholder frame style contexts to the style context from their frame parent rather than the out-of-flow frame. b=129350 r=attinasi sr=hyatt a=asa

This commit is contained in:
dbaron%fas.harvard.edu 2002-03-27 02:38:13 +00:00
Родитель 4d8709600c
Коммит 43acd755dd
26 изменённых файлов: 606 добавлений и 374 удалений

Просмотреть файл

@ -58,6 +58,7 @@
#include "nsRuleWalker.h"
#include "nsIHTMLDocument.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsHTMLAtoms.h"
#ifdef MOZ_PERF_METRICS
#include "nsITimeRecorder.h"
@ -1109,7 +1110,8 @@ nsIStyleContext* StyleSetImpl::ResolveStyleForNonElement(
mDocRuleProcessors ||
mOverrideRuleProcessors) {
EnsureRuleWalker(aPresContext);
result = GetContext(aPresContext, aParentContext, nsnull, aForceUnique);
result = GetContext(aPresContext, aParentContext,
nsHTMLAtoms::mozNonElementPseudo, aForceUnique);
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
}
}

Просмотреть файл

@ -58,6 +58,7 @@ HTML_ATOM(mozFirstLineFixup, ":-moz-first-line-fixup")
HTML_ATOM(mozLineFrame, ":-moz-line-frame")
HTML_ATOM(mozListBulletPseudo, ":-moz-list-bullet")
HTML_ATOM(mozListNumberPseudo, ":-moz-list-number")
HTML_ATOM(mozNonElementPseudo, ":-moz-non-element")
HTML_ATOM(mozSingleLineTextControlFrame, ":-moz-singleline-textcontrol-frame")
HTML_ATOM(mozFocusInnerPseudo, ":-moz-focus-inner")
HTML_ATOM(mozFocusOuterPseudo, ":-moz-focus-outer")

Просмотреть файл

@ -58,6 +58,7 @@ HTML_ATOM(mozFirstLineFixup, ":-moz-first-line-fixup")
HTML_ATOM(mozLineFrame, ":-moz-line-frame")
HTML_ATOM(mozListBulletPseudo, ":-moz-list-bullet")
HTML_ATOM(mozListNumberPseudo, ":-moz-list-number")
HTML_ATOM(mozNonElementPseudo, ":-moz-non-element")
HTML_ATOM(mozSingleLineTextControlFrame, ":-moz-singleline-textcontrol-frame")
HTML_ATOM(mozFocusInnerPseudo, ":-moz-focus-inner")
HTML_ATOM(mozFocusOuterPseudo, ":-moz-focus-outer")

Просмотреть файл

@ -139,7 +139,8 @@ LAYOUT_ATOM(viewportFrame, "ViewportFrame")
// Alphabetical list of frame property names
LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint*
LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL
LAYOUT_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame*
LAYOUT_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame*
LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*

Просмотреть файл

@ -384,7 +384,7 @@ GetSpecialSibling(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame** a
}
void* value;
aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation, 0, &value);
aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::IBSplitSpecialSibling, 0, &value);
*aResult = NS_STATIC_CAST(nsIFrame*, value);
}
@ -412,7 +412,8 @@ SetFrameIsSpecial(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame* aS
// Store the "special sibling" (if we were given one) with the
// first frame in the flow.
aFrameManager->SetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation,
aFrameManager->SetFrameProperty(aFrame,
nsLayoutAtoms::IBSplitSpecialSibling,
aSpecialSibling, nsnull);
}
}
@ -492,10 +493,7 @@ IsBlockFrame(nsIPresContext* aPresContext, nsIFrame* aFrame)
// don't we use display->IsBlockLevel() here?
const nsStyleDisplay* display;
aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_INLINE == display->mDisplay) {
return PR_FALSE;
}
return PR_TRUE;
return NS_STYLE_DISPLAY_INLINE != display->mDisplay;
}
static nsIFrame*
@ -527,6 +525,27 @@ FindLastBlock(nsIPresContext* aPresContext, nsIFrame* aKid)
return lastBlock;
}
/*
* Unlike the special (next) sibling, the special previous sibling
* property points only from the anonymous block to the original inline
* that preceded it. It is useful for finding the "special parent" of a
* frame (i.e., a frame from which a good parent style context can be
* obtained), one looks at the special previous sibling annotation of
* the real parent of the frame (if the real parent has
* NS_FRAME_IS_SPECIAL).
*/
inline void
MarkIBSpecialPrevSibling(nsIPresContext* aPresContext,
nsIFrameManager *aFrameManager,
nsIFrame *aAnonymousFrame,
nsIFrame *aSpecialParent)
{
aFrameManager->SetFrameProperty(aAnonymousFrame,
nsLayoutAtoms::IBSplitSpecialPrevSibling,
aSpecialParent,
nsnull);
}
/**
* Moves frames to a new parent, updating the style context and
* propagating relevant frame state bits. |aNewParentSC| may be null,
@ -3803,7 +3822,9 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
if (NS_SUCCEEDED(rv)) {
// The placeholder frame gets a pseudo style context
nsCOMPtr<nsIStyleContext> placeholderStyle;
aPresContext->ResolveStyleContextForNonElement(aStyleContext, PR_FALSE,
nsCOMPtr<nsIStyleContext> parentContext =
dont_AddRef(aStyleContext->GetParent());
aPresContext->ResolveStyleContextForNonElement(parentContext, PR_FALSE,
getter_AddRefs(placeholderStyle));
placeholderFrame->Init(aPresContext, aContent, aParentFrame,
placeholderStyle, nsnull);
@ -9231,15 +9252,18 @@ DeletingFrameSubtree(nsIPresContext* aPresContext,
if (aFrameManager) {
nsAutoVoidArray destroyQueue;
while (aFrame) {
// If it's a "special" block-in-inline frame, then we need to
// remember to delete our special siblings, too.
if (IsFrameSpecial(aFrame)) {
nsIFrame* specialSibling;
GetSpecialSibling(aFrameManager, aFrame, &specialSibling);
DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, specialSibling);
}
// If it's a "special" block-in-inline frame, then we need to
// remember to delete our special siblings, too. Since every one of
// the next-in-flows has the same special sibling, just do this
// once, rather than in the loop below.
if (IsFrameSpecial(aFrame)) {
nsIFrame* specialSibling;
GetSpecialSibling(aFrameManager, aFrame, &specialSibling);
DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager,
specialSibling);
}
while (aFrame) {
DoDeletingFrameSubtree(aPresContext, aPresShell, aFrameManager,
destroyQueue, aFrame, aFrame);
@ -10483,9 +10507,15 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
nsIFrame* primaryFrame;
shell->GetPrimaryFrameFor(aContent, &primaryFrame);
// Get the frame associated with the content whose style context is highest in the style context tree
nsIFrame* primaryStyleFrame = nsnull;
nsIFrame* primaryStyleFrame = primaryFrame;
if (primaryFrame) {
primaryFrame->GetStyleContextProvider(aPresContext, &primaryStyleFrame);
PRBool providerIsChild = PR_FALSE;
nsIFrame *styleContextProvider;
primaryFrame->GetParentStyleContextFrame(aPresContext,
&styleContextProvider,
&providerIsChild);
if (providerIsChild)
primaryStyleFrame = styleContextProvider;
}
PRBool reconstruct = PR_FALSE;
@ -11220,6 +11250,8 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
lastBlock->SetNextSibling(nsnull);
// Create "special" inline-block linkage between the frames
// XXXldb Do we really need to do this? It doesn't seem
// consistent with the use in ConstructInline.
SetFrameIsSpecial(state.mFrameManager, list1, list2);
SetFrameIsSpecial(state.mFrameManager, list2, list3);
SetFrameIsSpecial(state.mFrameManager, list3, nsnull);
@ -13742,6 +13774,8 @@ nsCSSFrameConstructor::ConstructInline(nsIPresShell* aPresShell,
// containing block will be reframed instead.
SetFrameIsSpecial(aState.mFrameManager, aNewFrame, blockFrame);
SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame);
MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager,
blockFrame, aNewFrame);
if (inlineFrame)
SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull);
@ -14169,6 +14203,7 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext,
// Create an anonymous inline frame that will parent
// aRightInlineChildFrame. The new frame won't have a parent yet:
// the recursion will parent it.
// XXXldb Why bother if |aRightInlineChildFrame| is null?
nsIFrame* inlineFrame = nsnull;
NS_NewInlineFrame(shell, &inlineFrame);
if (! inlineFrame)
@ -14196,6 +14231,9 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext,
SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame);
SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull);
MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager,
blockFrame, firstInFlow);
// If we have a continuation frame, then we need to break the
// continuation.
nsIFrame* nextInFlow;

Просмотреть файл

@ -417,7 +417,6 @@ private:
void ReResolveStyleContext(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIStyleContext* aParentContext,
nsIContent* aParentContent,
PRInt32 aAttrNameSpaceID,
nsIAtom* aAttribute,
@ -1275,8 +1274,6 @@ static void
VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
nsIStyleContext* aContext, nsIStyleContext* aParentContext)
{
nsIAtom* frameType;
// get the contexts not provided
if (!aContext) {
aFrame->GetStyleContext(&aContext);
@ -1289,24 +1286,15 @@ VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
// Get the correct parent context from the frame
// - if the frame is a placeholder, we get the out of flow frame's context
// as the parent context instead of asking the frame
aFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder
// get out of flow frame's context as the parent context
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)aFrame)->GetOutOfFlowFrame();
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
outOfFlowFrame->GetStyleContext(&aParentContext);
} else {
// get the parent context from the frame (indirectly)
nsIFrame* providerFrame = nsnull;
aFrame->GetStyleContextProvider(aPresContext, &providerFrame);
ENSURE_TRUE(providerFrame);
nsCOMPtr<nsIStyleContext> providerContext;
providerFrame->GetStyleContext(getter_AddRefs(providerContext));
ENSURE_TRUE(providerContext);
aParentContext = providerContext->GetParent(); // released later
// aParentContext could still be null, since some contexts don't have parents
}
NS_IF_RELEASE(frameType);
// get the parent context from the frame (indirectly)
nsIFrame* providerFrame = nsnull;
PRBool providerIsChild;
aFrame->GetParentStyleContextFrame(aPresContext,
&providerFrame, &providerIsChild);
if (providerFrame)
providerFrame->GetStyleContext(&aParentContext);
// aParentContext could still be null
} else {
// addref the parent context so we can release it at end
NS_ADDREF(aParentContext);
@ -1351,7 +1339,7 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext*
nsIStyleContext* context;
aFrame->GetStyleContext(&context);
VerifyContextParent(aPresContext, aFrame, context, aParentContext);
VerifyContextParent(aPresContext, aFrame, context, nsnull);
PRInt32 listIndex = 0;
nsIAtom* childList = nsnull;
@ -1372,15 +1360,13 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext*
// then verify the placeholder's context
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame();
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
nsIStyleContext* outOfFlowContext;
// recurse to out of flow frame, letting the parent context get resolved
VerifyStyleTree(aPresContext, outOfFlowFrame, nsnull);
// verify placeholder using the out of flow's context as parent context
outOfFlowFrame->GetStyleContext(&outOfFlowContext);
VerifyContextParent(aPresContext,child, nsnull, outOfFlowContext);
NS_IF_RELEASE(outOfFlowContext);
// verify placeholder using the parent frame's context as
// parent context
VerifyContextParent(aPresContext, child, nsnull, nsnull);
}
else { // regular frame
VerifyStyleTree(aPresContext, child, nsnull);
@ -1585,7 +1571,6 @@ CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext,
void
FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIStyleContext* aParentContextIn,
nsIContent* aParentContent,
PRInt32 aAttrNameSpaceID,
nsIAtom* aAttribute,
@ -1620,73 +1605,51 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
nsCOMPtr<nsIStyleContext> parentContext;
nsIFrame* resolvedDescendant = nsnull;
// Get the frame providing the style context. If it differs from aFrame, then
// reslove the provider first, since the provider's context is the parent of aFrame's
nsIFrame* resolvedChild = nsnull;
// Get the frame providing the parent style context. If it is a
// child, then resolve the provider first.
nsIFrame* providerFrame = nsnull;
aFrame->GetStyleContextProvider(aPresContext, &providerFrame);
ENSURE_TRUE(providerFrame);
if (providerFrame == aFrame) {
if (aParentContextIn) {
parentContext = aParentContextIn;
NOISY_TRACE_FRAME("non-null parent context provided: using it and assuming already resolved",aFrame);
} else {
nsIFrame* parentFrame;
aFrame->GetParent(&parentFrame);
if (parentFrame) {
parentFrame->GetStyleContext(getter_AddRefs(parentContext));
}
}
PRBool providerIsChild = PR_FALSE;
aFrame->GetParentStyleContextFrame(aPresContext,
&providerFrame, &providerIsChild);
if (!providerIsChild) {
if (providerFrame)
providerFrame->GetStyleContext(getter_AddRefs(parentContext));
}
else {
#ifdef DEBUG
// check to make sure that the provider is the child of aFrame
nsIFrame* providerFrameParent;
providerFrame->GetParent(&providerFrameParent);
NS_ASSERTION(providerFrameParent == aFrame, "invalid style context provider");
#endif
// resolve the provider here (before aFrame below)
nsCOMPtr<nsIStyleContext> providerContextParent;
nsIFrame* grandParentFrame;
aFrame->GetParent(&grandParentFrame);
if (grandParentFrame) {
grandParentFrame->GetStyleContext(getter_AddRefs(providerContextParent));
}
ReResolveStyleContext(aPresContext, providerFrame, providerContextParent, content,
aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, aResultChange);
// the provider's new context becomes the parent context of aFrame's context
ReResolveStyleContext(aPresContext, providerFrame, content,
aAttrNameSpaceID, aAttribute, aChangeList,
aMinChange, aResultChange);
// The provider's new context becomes the parent context of
// aFrame's context.
providerFrame->GetStyleContext(getter_AddRefs(parentContext));
resolvedDescendant = providerFrame; // don't want to re-resolve the provider again
// Set |resolvedChild| so we don't bother resolving the
// provider again.
resolvedChild = providerFrame;
}
// do primary context
nsIStyleContext* newContext = nsnull;
if (pseudoTag) {
nsIContent* pseudoContent = (aParentContent) ? aParentContent : localContent;
aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, parentContext,
if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) {
NS_ASSERTION(localContent,
"non pseudo-element frame without content node");
aPresContext->ResolveStyleContextForNonElement(parentContext,
PR_TRUE, &newContext);
}
else if (pseudoTag) {
nsIContent* pseudoContent =
aParentContent ? aParentContent : localContent;
aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag,
parentContext,
PR_FALSE, &newContext);
NS_RELEASE(pseudoTag);
}
else {
NS_ASSERTION(localContent,
"non pseudo-element frame without content node");
// XXX This frame type check is a little ugly. However, it should
// be cheaper than doing useless style resolution on placeholder
// frames, and it should be able to go away if we make it so that
// placeholder frames don't have style contexts at all.
//
// XXX We also probably need to descend into the style contexts of
// the placeholder's out-of-flow frame.
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
if (content->IsContentOfType(nsIContent::eELEMENT) &&
frameType != nsLayoutAtoms::placeholderFrame) {
aPresContext->ResolveStyleContextFor(content, parentContext,
PR_TRUE, &newContext);
} else {
aPresContext->ResolveStyleContextForNonElement(parentContext,
PR_TRUE, &newContext);
}
aPresContext->ResolveStyleContextFor(content, parentContext,
PR_TRUE, &newContext);
}
NS_ASSERTION(newContext, "failed to get new style context");
if (newContext) {
@ -1730,7 +1693,9 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
if (oldExtraContext) {
nsIStyleContext* newExtraContext = nsnull;
oldExtraContext->GetPseudoType(pseudoTag);
NS_ASSERTION(pseudoTag, "extra style context is not pseudo element");
NS_ASSERTION(pseudoTag &&
pseudoTag != nsHTMLAtoms::mozNonElementPseudo,
"extra style context is not pseudo element");
result = aPresContext->ResolvePseudoStyleContextFor(content, pseudoTag, newContext,
PR_FALSE, &newExtraContext);
NS_RELEASE(pseudoTag);
@ -1770,6 +1735,10 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
aPresContext->ResolveStyleContextFor(undisplayed->mContent, newContext,
PR_TRUE, &undisplayedContext);
}
else if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) {
aPresContext->ResolveStyleContextForNonElement(newContext,
PR_TRUE, &undisplayedContext);
}
else { // pseudo element
NS_ASSERTION(pseudoTag, "pseudo element without tag");
aPresContext->ResolvePseudoStyleContextFor(localContent, pseudoTag, newContext, PR_FALSE,
@ -1786,8 +1755,12 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
aChangeList.AppendChange(nsnull, ((undisplayed->mContent) ? undisplayed->mContent : localContent),
NS_STYLE_HINT_FRAMECHANGE);
NS_RELEASE(undisplayedContext);
} else {
// update the undisplayed node with the new context
NS_RELEASE(undisplayed->mStyle);
undisplayed->mStyle = undisplayedContext;
}
NS_RELEASE(undisplayedContext);
}
undisplayed = undisplayed->mNext;
}
@ -1805,42 +1778,40 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
PRInt32 listIndex = 0;
nsIAtom* childList = nsnull;
PRInt32 childChange;
nsIFrame* child;
do {
child = nsnull;
nsIFrame* child = nsnull;
result = aFrame->FirstChild(aPresContext, childList, &child);
while ((NS_SUCCEEDED(result)) && (child)) {
while (NS_SUCCEEDED(result) && child) {
nsFrameState state;
child->GetFrameState(&state);
if (NS_FRAME_OUT_OF_FLOW != (state & NS_FRAME_OUT_OF_FLOW)) {
if (!(state & NS_FRAME_OUT_OF_FLOW)) {
// only do frames that are in flow
nsCOMPtr<nsIAtom> frameType;
child->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::placeholderFrame == frameType.get()) { // placeholder
// get out of flow frame and recurse there
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame();
if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder
// get out of flow frame and recur there
nsIFrame* outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*,child)->GetOutOfFlowFrame();
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
NS_ASSERTION(outOfFlowFrame != resolvedChild,
"out-of-flow frame not a true descendant");
if (outOfFlowFrame != resolvedDescendant) {
ReResolveStyleContext(aPresContext, outOfFlowFrame, nsnull, content,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, childChange);
} else {
NOISY_TRACE("out of flow frame already resolved as descendent\n");
}
// |nsFrame::GetParentStyleContextFrame| checks being out
// of flow so that this works correctly.
ReResolveStyleContext(aPresContext, outOfFlowFrame, content,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, childChange);
// reresolve placeholder's context under out of flow frame
nsIStyleContext* outOfFlowContext;
outOfFlowFrame->GetStyleContext(&outOfFlowContext);
ReResolveStyleContext(aPresContext, child, outOfFlowContext, content,
// reresolve placeholder's context under the same parent
// as the out-of-flow frame
ReResolveStyleContext(aPresContext, child, content,
kNameSpaceID_Unknown, nsnull,
aChangeList, aMinChange, childChange);
NS_RELEASE(outOfFlowContext);
}
else { // regular child frame
if (child != resolvedDescendant) {
ReResolveStyleContext(aPresContext, child, nsnull, content,
if (child != resolvedChild) {
ReResolveStyleContext(aPresContext, child, content,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, childChange);
} else {
@ -1884,18 +1855,13 @@ FrameManager::ComputeStyleChangeFor(nsIPresContext* aPresContext,
#endif
do {
nsIStyleContext* styleContext = nsnull;
frame->GetStyleContext(&styleContext);
nsIStyleContext* parentContext = styleContext->GetParent();
PRInt32 frameChange;
ReResolveStyleContext(aPresContext, frame, parentContext, nsnull,
ReResolveStyleContext(aPresContext, frame, nsnull,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, frameChange);
#ifdef NS_DEBUG
VerifyStyleTree(aPresContext, frame, parentContext);
VerifyStyleTree(aPresContext, frame, nsnull);
#endif
NS_IF_RELEASE(parentContext);
NS_RELEASE(styleContext);
if (aTopLevelChange < frameChange) {
aTopLevelChange = frameChange;
}

Просмотреть файл

@ -139,7 +139,8 @@ LAYOUT_ATOM(viewportFrame, "ViewportFrame")
// Alphabetical list of frame property names
LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint*
LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL
LAYOUT_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame*
LAYOUT_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame*
LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*

Просмотреть файл

@ -1091,15 +1091,25 @@ public:
PRBool aCommandAdded) = 0;
/**
* Get the frame that is the primary frame associated with the content.
* aProviderFrame == this except in the case of an outer table, in
* which case it is the inner table.
* Get the frame whose style context should be the parent of this
* frame's style context (i.e., provide the parent style context).
* This frame must either be an ancestor of this frame or a child. If
* this frame returns a child frame, then the child frame must be sure
* to return a grandparent or higher!
*
* @param aPresContext: PresContext
* @param aProviderFrame: Set to the primary frame associated with the content
* @param aProviderFrame: The frame whose style context should be the
* parent of this frame's style context. Null
* is permitted, and means that this frame's
* style context should be the root of the
* style context tree.
* @param aIsChild: True if |aProviderFrame| is set to a child
* of this frame; false if it is an ancestor or
* null.
*/
NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame) = 0;
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild) = 0;
/**
* Determines whether a frame is visible for painting

Просмотреть файл

@ -336,33 +336,28 @@ nsFrame::Init(nsIPresContext* aPresContext,
mContent = aContent;
NS_IF_ADDREF(mContent);
mParent = aParent;
nsFrameState state;
if (aPrevInFlow) {
// Make sure the general flags bits are the same
nsFrameState state;
aPrevInFlow->GetFrameState(&state);
if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) {
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
}
if (state & NS_FRAME_REPLACED_ELEMENT) {
mState |= NS_FRAME_REPLACED_ELEMENT;
}
if (state & NS_FRAME_SELECTED_CONTENT) {
mState |= NS_FRAME_SELECTED_CONTENT;
}
if (state & NS_FRAME_INDEPENDENT_SELECTION) {
mState |= NS_FRAME_INDEPENDENT_SELECTION;
}
// Make bits that are currently on (see constructor) the same:
mState &= state | ~(NS_FRAME_SYNC_FRAME_AND_VIEW);
// Make bits that are currently off (see constructor) the same:
mState |= state & (NS_FRAME_REPLACED_ELEMENT |
NS_FRAME_SELECTED_CONTENT |
NS_FRAME_INDEPENDENT_SELECTION |
NS_FRAME_IS_SPECIAL);
}
if(mParent)
{
if (mParent) {
nsFrameState state;
mParent->GetFrameState(&state);
if (state & NS_FRAME_INDEPENDENT_SELECTION) {
mState |= NS_FRAME_INDEPENDENT_SELECTION;
}
if (state & NS_FRAME_GENERATED_CONTENT){
mState |= NS_FRAME_GENERATED_CONTENT;
}
// Make bits that are currently off (see constructor) the same:
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
NS_FRAME_GENERATED_CONTENT);
}
return SetStyleContext(aPresContext, aContext);
}
@ -4006,10 +4001,85 @@ nsFrame::ReflowCommandNotify(nsIPresShell* aShell,
}
NS_IMETHODIMP
nsFrame::GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame)
nsFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
*aProviderFrame = this;
return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
}
nsresult
nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
*aIsChild = PR_FALSE;
if (!(mState & NS_FRAME_OUT_OF_FLOW)) {
// If this frame is one of the blocks that split an inline, we must
// return the "special" inline parent, i.e., the parent that this
// frame would have if we didn't mangle the frame structure.
return GetIBSpecialParent(aPresContext, aProviderFrame);
}
// For out-of-flow frames, we must resolve underneath the
// placeholder's parent.
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
nsIFrame *placeholder;
frameManager->GetPlaceholderFrameFor(this, &placeholder);
if (!placeholder) {
NS_NOTREACHED("no placeholder frame for out-of-flow frame");
GetIBSpecialParent(aPresContext, aProviderFrame);
return NS_ERROR_FAILURE;
}
return NS_STATIC_CAST(nsFrame*, placeholder)->GetParent(aProviderFrame);
}
/**
* Get the parent, corrected for the mangled frame tree resulting from
* having a block within an inline. The result only differs from the
* result of |GetParent| when |GetParent| returns an anonymous block
* that was created for an element that was 'display: inline' because
* that element contained a block.
*/
nsresult
nsFrame::GetIBSpecialParent(nsIPresContext* aPresContext,
nsIFrame** aSpecialParent)
{
*aSpecialParent = mParent;
if (mParent) {
nsFrameState parentState;
mParent->GetFrameState(&parentState);
if (parentState & NS_FRAME_IS_SPECIAL) {
// Find the first-in-flow of the parent. (Ugh. This ends up
// being O(N^2) when it is called O(N) times.)
nsIFrame *parentFIF = mParent;
for (;;) {
nsIFrame *prevInFlow;
parentFIF->GetPrevInFlow(&prevInFlow);
if (!prevInFlow)
break;
parentFIF = prevInFlow;
}
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
nsIFrame *specialParent;
nsresult rv =
frameManager->GetFrameProperty(parentFIF,
nsLayoutAtoms::IBSplitSpecialPrevSibling,
0, (void**)&specialParent);
if (NS_OK == rv) {
NS_ASSERTION(specialParent, "null special parent");
*aSpecialParent = specialParent;
}
}
}
return NS_OK;
}

Просмотреть файл

@ -282,8 +282,9 @@ public:
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame);
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
// Check Style Visibility and mState for Selection (when printing)
NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext,
@ -375,6 +376,18 @@ public:
nsIAtom* aAttribute,
nsIAtom* aListName);
// Do the work for getting the parent style context frame so that
// other frame's |GetParentStyleContextFrame| methods can call this
// method on *another* frame. (This function handles out-of-flow
// frames by using the frame manager's placeholder map and it handles
// block-within-inline by calling |GetIBSpecialParent|.)
nsresult DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
nsresult GetIBSpecialParent(nsIPresContext* aPresContext,
nsIFrame** aSpecialParent);
//Mouse Capturing code used by the frames to tell the view to capture all the following events
NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
PRBool IsMouseCaptured(nsIPresContext* aPresContext);

Просмотреть файл

@ -1091,15 +1091,25 @@ public:
PRBool aCommandAdded) = 0;
/**
* Get the frame that is the primary frame associated with the content.
* aProviderFrame == this except in the case of an outer table, in
* which case it is the inner table.
* Get the frame whose style context should be the parent of this
* frame's style context (i.e., provide the parent style context).
* This frame must either be an ancestor of this frame or a child. If
* this frame returns a child frame, then the child frame must be sure
* to return a grandparent or higher!
*
* @param aPresContext: PresContext
* @param aProviderFrame: Set to the primary frame associated with the content
* @param aProviderFrame: The frame whose style context should be the
* parent of this frame's style context. Null
* is permitted, and means that this frame's
* style context should be the root of the
* style context tree.
* @param aIsChild: True if |aProviderFrame| is set to a child
* of this frame; false if it is an ancestor or
* null.
*/
NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame) = 0;
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild) = 0;
/**
* Determines whether a frame is visible for painting

Просмотреть файл

@ -55,19 +55,6 @@ nsSplittableFrame::Init(nsIPresContext* aPresContext,
// Hook the frame into the flow
mPrevInFlow = aPrevInFlow;
aPrevInFlow->SetNextInFlow(this);
// Make sure the general flags bits are the same
nsFrameState state;
aPrevInFlow->GetFrameState(&state);
if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) {
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
}
if (state & NS_FRAME_REPLACED_ELEMENT) {
mState |= NS_FRAME_REPLACED_ELEMENT;
}
if (state & NS_FRAME_SELECTED_CONTENT) {
mState |= NS_FRAME_SELECTED_CONTENT;
}
}
return rv;

Просмотреть файл

@ -336,33 +336,28 @@ nsFrame::Init(nsIPresContext* aPresContext,
mContent = aContent;
NS_IF_ADDREF(mContent);
mParent = aParent;
nsFrameState state;
if (aPrevInFlow) {
// Make sure the general flags bits are the same
nsFrameState state;
aPrevInFlow->GetFrameState(&state);
if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) {
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
}
if (state & NS_FRAME_REPLACED_ELEMENT) {
mState |= NS_FRAME_REPLACED_ELEMENT;
}
if (state & NS_FRAME_SELECTED_CONTENT) {
mState |= NS_FRAME_SELECTED_CONTENT;
}
if (state & NS_FRAME_INDEPENDENT_SELECTION) {
mState |= NS_FRAME_INDEPENDENT_SELECTION;
}
// Make bits that are currently on (see constructor) the same:
mState &= state | ~(NS_FRAME_SYNC_FRAME_AND_VIEW);
// Make bits that are currently off (see constructor) the same:
mState |= state & (NS_FRAME_REPLACED_ELEMENT |
NS_FRAME_SELECTED_CONTENT |
NS_FRAME_INDEPENDENT_SELECTION |
NS_FRAME_IS_SPECIAL);
}
if(mParent)
{
if (mParent) {
nsFrameState state;
mParent->GetFrameState(&state);
if (state & NS_FRAME_INDEPENDENT_SELECTION) {
mState |= NS_FRAME_INDEPENDENT_SELECTION;
}
if (state & NS_FRAME_GENERATED_CONTENT){
mState |= NS_FRAME_GENERATED_CONTENT;
}
// Make bits that are currently off (see constructor) the same:
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
NS_FRAME_GENERATED_CONTENT);
}
return SetStyleContext(aPresContext, aContext);
}
@ -4006,10 +4001,85 @@ nsFrame::ReflowCommandNotify(nsIPresShell* aShell,
}
NS_IMETHODIMP
nsFrame::GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame)
nsFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
*aProviderFrame = this;
return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
}
nsresult
nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
*aIsChild = PR_FALSE;
if (!(mState & NS_FRAME_OUT_OF_FLOW)) {
// If this frame is one of the blocks that split an inline, we must
// return the "special" inline parent, i.e., the parent that this
// frame would have if we didn't mangle the frame structure.
return GetIBSpecialParent(aPresContext, aProviderFrame);
}
// For out-of-flow frames, we must resolve underneath the
// placeholder's parent.
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
nsIFrame *placeholder;
frameManager->GetPlaceholderFrameFor(this, &placeholder);
if (!placeholder) {
NS_NOTREACHED("no placeholder frame for out-of-flow frame");
GetIBSpecialParent(aPresContext, aProviderFrame);
return NS_ERROR_FAILURE;
}
return NS_STATIC_CAST(nsFrame*, placeholder)->GetParent(aProviderFrame);
}
/**
* Get the parent, corrected for the mangled frame tree resulting from
* having a block within an inline. The result only differs from the
* result of |GetParent| when |GetParent| returns an anonymous block
* that was created for an element that was 'display: inline' because
* that element contained a block.
*/
nsresult
nsFrame::GetIBSpecialParent(nsIPresContext* aPresContext,
nsIFrame** aSpecialParent)
{
*aSpecialParent = mParent;
if (mParent) {
nsFrameState parentState;
mParent->GetFrameState(&parentState);
if (parentState & NS_FRAME_IS_SPECIAL) {
// Find the first-in-flow of the parent. (Ugh. This ends up
// being O(N^2) when it is called O(N) times.)
nsIFrame *parentFIF = mParent;
for (;;) {
nsIFrame *prevInFlow;
parentFIF->GetPrevInFlow(&prevInFlow);
if (!prevInFlow)
break;
parentFIF = prevInFlow;
}
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
nsIFrame *specialParent;
nsresult rv =
frameManager->GetFrameProperty(parentFIF,
nsLayoutAtoms::IBSplitSpecialPrevSibling,
0, (void**)&specialParent);
if (NS_OK == rv) {
NS_ASSERTION(specialParent, "null special parent");
*aSpecialParent = specialParent;
}
}
}
return NS_OK;
}

Просмотреть файл

@ -282,8 +282,9 @@ public:
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame);
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
// Check Style Visibility and mState for Selection (when printing)
NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext,
@ -375,6 +376,18 @@ public:
nsIAtom* aAttribute,
nsIAtom* aListName);
// Do the work for getting the parent style context frame so that
// other frame's |GetParentStyleContextFrame| methods can call this
// method on *another* frame. (This function handles out-of-flow
// frames by using the frame manager's placeholder map and it handles
// block-within-inline by calling |GetIBSpecialParent|.)
nsresult DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
nsresult GetIBSpecialParent(nsIPresContext* aPresContext,
nsIFrame** aSpecialParent);
//Mouse Capturing code used by the frames to tell the view to capture all the following events
NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
PRBool IsMouseCaptured(nsIPresContext* aPresContext);

Просмотреть файл

@ -417,7 +417,6 @@ private:
void ReResolveStyleContext(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIStyleContext* aParentContext,
nsIContent* aParentContent,
PRInt32 aAttrNameSpaceID,
nsIAtom* aAttribute,
@ -1275,8 +1274,6 @@ static void
VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
nsIStyleContext* aContext, nsIStyleContext* aParentContext)
{
nsIAtom* frameType;
// get the contexts not provided
if (!aContext) {
aFrame->GetStyleContext(&aContext);
@ -1289,24 +1286,15 @@ VerifyContextParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
// Get the correct parent context from the frame
// - if the frame is a placeholder, we get the out of flow frame's context
// as the parent context instead of asking the frame
aFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder
// get out of flow frame's context as the parent context
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)aFrame)->GetOutOfFlowFrame();
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
outOfFlowFrame->GetStyleContext(&aParentContext);
} else {
// get the parent context from the frame (indirectly)
nsIFrame* providerFrame = nsnull;
aFrame->GetStyleContextProvider(aPresContext, &providerFrame);
ENSURE_TRUE(providerFrame);
nsCOMPtr<nsIStyleContext> providerContext;
providerFrame->GetStyleContext(getter_AddRefs(providerContext));
ENSURE_TRUE(providerContext);
aParentContext = providerContext->GetParent(); // released later
// aParentContext could still be null, since some contexts don't have parents
}
NS_IF_RELEASE(frameType);
// get the parent context from the frame (indirectly)
nsIFrame* providerFrame = nsnull;
PRBool providerIsChild;
aFrame->GetParentStyleContextFrame(aPresContext,
&providerFrame, &providerIsChild);
if (providerFrame)
providerFrame->GetStyleContext(&aParentContext);
// aParentContext could still be null
} else {
// addref the parent context so we can release it at end
NS_ADDREF(aParentContext);
@ -1351,7 +1339,7 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext*
nsIStyleContext* context;
aFrame->GetStyleContext(&context);
VerifyContextParent(aPresContext, aFrame, context, aParentContext);
VerifyContextParent(aPresContext, aFrame, context, nsnull);
PRInt32 listIndex = 0;
nsIAtom* childList = nsnull;
@ -1372,15 +1360,13 @@ VerifyStyleTree(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIStyleContext*
// then verify the placeholder's context
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame();
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
nsIStyleContext* outOfFlowContext;
// recurse to out of flow frame, letting the parent context get resolved
VerifyStyleTree(aPresContext, outOfFlowFrame, nsnull);
// verify placeholder using the out of flow's context as parent context
outOfFlowFrame->GetStyleContext(&outOfFlowContext);
VerifyContextParent(aPresContext,child, nsnull, outOfFlowContext);
NS_IF_RELEASE(outOfFlowContext);
// verify placeholder using the parent frame's context as
// parent context
VerifyContextParent(aPresContext, child, nsnull, nsnull);
}
else { // regular frame
VerifyStyleTree(aPresContext, child, nsnull);
@ -1585,7 +1571,6 @@ CaptureChange(nsIStyleContext* aOldContext, nsIStyleContext* aNewContext,
void
FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIStyleContext* aParentContextIn,
nsIContent* aParentContent,
PRInt32 aAttrNameSpaceID,
nsIAtom* aAttribute,
@ -1620,73 +1605,51 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
}
nsCOMPtr<nsIStyleContext> parentContext;
nsIFrame* resolvedDescendant = nsnull;
// Get the frame providing the style context. If it differs from aFrame, then
// reslove the provider first, since the provider's context is the parent of aFrame's
nsIFrame* resolvedChild = nsnull;
// Get the frame providing the parent style context. If it is a
// child, then resolve the provider first.
nsIFrame* providerFrame = nsnull;
aFrame->GetStyleContextProvider(aPresContext, &providerFrame);
ENSURE_TRUE(providerFrame);
if (providerFrame == aFrame) {
if (aParentContextIn) {
parentContext = aParentContextIn;
NOISY_TRACE_FRAME("non-null parent context provided: using it and assuming already resolved",aFrame);
} else {
nsIFrame* parentFrame;
aFrame->GetParent(&parentFrame);
if (parentFrame) {
parentFrame->GetStyleContext(getter_AddRefs(parentContext));
}
}
PRBool providerIsChild = PR_FALSE;
aFrame->GetParentStyleContextFrame(aPresContext,
&providerFrame, &providerIsChild);
if (!providerIsChild) {
if (providerFrame)
providerFrame->GetStyleContext(getter_AddRefs(parentContext));
}
else {
#ifdef DEBUG
// check to make sure that the provider is the child of aFrame
nsIFrame* providerFrameParent;
providerFrame->GetParent(&providerFrameParent);
NS_ASSERTION(providerFrameParent == aFrame, "invalid style context provider");
#endif
// resolve the provider here (before aFrame below)
nsCOMPtr<nsIStyleContext> providerContextParent;
nsIFrame* grandParentFrame;
aFrame->GetParent(&grandParentFrame);
if (grandParentFrame) {
grandParentFrame->GetStyleContext(getter_AddRefs(providerContextParent));
}
ReResolveStyleContext(aPresContext, providerFrame, providerContextParent, content,
aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, aResultChange);
// the provider's new context becomes the parent context of aFrame's context
ReResolveStyleContext(aPresContext, providerFrame, content,
aAttrNameSpaceID, aAttribute, aChangeList,
aMinChange, aResultChange);
// The provider's new context becomes the parent context of
// aFrame's context.
providerFrame->GetStyleContext(getter_AddRefs(parentContext));
resolvedDescendant = providerFrame; // don't want to re-resolve the provider again
// Set |resolvedChild| so we don't bother resolving the
// provider again.
resolvedChild = providerFrame;
}
// do primary context
nsIStyleContext* newContext = nsnull;
if (pseudoTag) {
nsIContent* pseudoContent = (aParentContent) ? aParentContent : localContent;
aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, parentContext,
if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) {
NS_ASSERTION(localContent,
"non pseudo-element frame without content node");
aPresContext->ResolveStyleContextForNonElement(parentContext,
PR_TRUE, &newContext);
}
else if (pseudoTag) {
nsIContent* pseudoContent =
aParentContent ? aParentContent : localContent;
aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag,
parentContext,
PR_FALSE, &newContext);
NS_RELEASE(pseudoTag);
}
else {
NS_ASSERTION(localContent,
"non pseudo-element frame without content node");
// XXX This frame type check is a little ugly. However, it should
// be cheaper than doing useless style resolution on placeholder
// frames, and it should be able to go away if we make it so that
// placeholder frames don't have style contexts at all.
//
// XXX We also probably need to descend into the style contexts of
// the placeholder's out-of-flow frame.
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
if (content->IsContentOfType(nsIContent::eELEMENT) &&
frameType != nsLayoutAtoms::placeholderFrame) {
aPresContext->ResolveStyleContextFor(content, parentContext,
PR_TRUE, &newContext);
} else {
aPresContext->ResolveStyleContextForNonElement(parentContext,
PR_TRUE, &newContext);
}
aPresContext->ResolveStyleContextFor(content, parentContext,
PR_TRUE, &newContext);
}
NS_ASSERTION(newContext, "failed to get new style context");
if (newContext) {
@ -1730,7 +1693,9 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
if (oldExtraContext) {
nsIStyleContext* newExtraContext = nsnull;
oldExtraContext->GetPseudoType(pseudoTag);
NS_ASSERTION(pseudoTag, "extra style context is not pseudo element");
NS_ASSERTION(pseudoTag &&
pseudoTag != nsHTMLAtoms::mozNonElementPseudo,
"extra style context is not pseudo element");
result = aPresContext->ResolvePseudoStyleContextFor(content, pseudoTag, newContext,
PR_FALSE, &newExtraContext);
NS_RELEASE(pseudoTag);
@ -1770,6 +1735,10 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
aPresContext->ResolveStyleContextFor(undisplayed->mContent, newContext,
PR_TRUE, &undisplayedContext);
}
else if (pseudoTag == nsHTMLAtoms::mozNonElementPseudo) {
aPresContext->ResolveStyleContextForNonElement(newContext,
PR_TRUE, &undisplayedContext);
}
else { // pseudo element
NS_ASSERTION(pseudoTag, "pseudo element without tag");
aPresContext->ResolvePseudoStyleContextFor(localContent, pseudoTag, newContext, PR_FALSE,
@ -1786,8 +1755,12 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
aChangeList.AppendChange(nsnull, ((undisplayed->mContent) ? undisplayed->mContent : localContent),
NS_STYLE_HINT_FRAMECHANGE);
NS_RELEASE(undisplayedContext);
} else {
// update the undisplayed node with the new context
NS_RELEASE(undisplayed->mStyle);
undisplayed->mStyle = undisplayedContext;
}
NS_RELEASE(undisplayedContext);
}
undisplayed = undisplayed->mNext;
}
@ -1805,42 +1778,40 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext,
PRInt32 listIndex = 0;
nsIAtom* childList = nsnull;
PRInt32 childChange;
nsIFrame* child;
do {
child = nsnull;
nsIFrame* child = nsnull;
result = aFrame->FirstChild(aPresContext, childList, &child);
while ((NS_SUCCEEDED(result)) && (child)) {
while (NS_SUCCEEDED(result) && child) {
nsFrameState state;
child->GetFrameState(&state);
if (NS_FRAME_OUT_OF_FLOW != (state & NS_FRAME_OUT_OF_FLOW)) {
if (!(state & NS_FRAME_OUT_OF_FLOW)) {
// only do frames that are in flow
nsCOMPtr<nsIAtom> frameType;
child->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::placeholderFrame == frameType.get()) { // placeholder
// get out of flow frame and recurse there
nsIFrame* outOfFlowFrame = ((nsPlaceholderFrame*)child)->GetOutOfFlowFrame();
if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder
// get out of flow frame and recur there
nsIFrame* outOfFlowFrame =
NS_STATIC_CAST(nsPlaceholderFrame*,child)->GetOutOfFlowFrame();
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
NS_ASSERTION(outOfFlowFrame != resolvedChild,
"out-of-flow frame not a true descendant");
if (outOfFlowFrame != resolvedDescendant) {
ReResolveStyleContext(aPresContext, outOfFlowFrame, nsnull, content,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, childChange);
} else {
NOISY_TRACE("out of flow frame already resolved as descendent\n");
}
// |nsFrame::GetParentStyleContextFrame| checks being out
// of flow so that this works correctly.
ReResolveStyleContext(aPresContext, outOfFlowFrame, content,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, childChange);
// reresolve placeholder's context under out of flow frame
nsIStyleContext* outOfFlowContext;
outOfFlowFrame->GetStyleContext(&outOfFlowContext);
ReResolveStyleContext(aPresContext, child, outOfFlowContext, content,
// reresolve placeholder's context under the same parent
// as the out-of-flow frame
ReResolveStyleContext(aPresContext, child, content,
kNameSpaceID_Unknown, nsnull,
aChangeList, aMinChange, childChange);
NS_RELEASE(outOfFlowContext);
}
else { // regular child frame
if (child != resolvedDescendant) {
ReResolveStyleContext(aPresContext, child, nsnull, content,
if (child != resolvedChild) {
ReResolveStyleContext(aPresContext, child, content,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, childChange);
} else {
@ -1884,18 +1855,13 @@ FrameManager::ComputeStyleChangeFor(nsIPresContext* aPresContext,
#endif
do {
nsIStyleContext* styleContext = nsnull;
frame->GetStyleContext(&styleContext);
nsIStyleContext* parentContext = styleContext->GetParent();
PRInt32 frameChange;
ReResolveStyleContext(aPresContext, frame, parentContext, nsnull,
ReResolveStyleContext(aPresContext, frame, nsnull,
aAttrNameSpaceID, aAttribute,
aChangeList, aMinChange, frameChange);
#ifdef NS_DEBUG
VerifyStyleTree(aPresContext, frame, parentContext);
VerifyStyleTree(aPresContext, frame, nsnull);
#endif
NS_IF_RELEASE(parentContext);
NS_RELEASE(styleContext);
if (aTopLevelChange < frameChange) {
aTopLevelChange = frameChange;
}

Просмотреть файл

@ -55,19 +55,6 @@ nsSplittableFrame::Init(nsIPresContext* aPresContext,
// Hook the frame into the flow
mPrevInFlow = aPrevInFlow;
aPrevInFlow->SetNextInFlow(this);
// Make sure the general flags bits are the same
nsFrameState state;
aPrevInFlow->GetFrameState(&state);
if ((state & NS_FRAME_SYNC_FRAME_AND_VIEW) == 0) {
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW;
}
if (state & NS_FRAME_REPLACED_ELEMENT) {
mState |= NS_FRAME_REPLACED_ELEMENT;
}
if (state & NS_FRAME_SELECTED_CONTENT) {
mState |= NS_FRAME_SELECTED_CONTENT;
}
}
return rv;

Просмотреть файл

@ -384,7 +384,7 @@ GetSpecialSibling(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame** a
}
void* value;
aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation, 0, &value);
aFrameManager->GetFrameProperty(aFrame, nsLayoutAtoms::IBSplitSpecialSibling, 0, &value);
*aResult = NS_STATIC_CAST(nsIFrame*, value);
}
@ -412,7 +412,8 @@ SetFrameIsSpecial(nsIFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame* aS
// Store the "special sibling" (if we were given one) with the
// first frame in the flow.
aFrameManager->SetFrameProperty(aFrame, nsLayoutAtoms::inlineFrameAnnotation,
aFrameManager->SetFrameProperty(aFrame,
nsLayoutAtoms::IBSplitSpecialSibling,
aSpecialSibling, nsnull);
}
}
@ -492,10 +493,7 @@ IsBlockFrame(nsIPresContext* aPresContext, nsIFrame* aFrame)
// don't we use display->IsBlockLevel() here?
const nsStyleDisplay* display;
aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
if (NS_STYLE_DISPLAY_INLINE == display->mDisplay) {
return PR_FALSE;
}
return PR_TRUE;
return NS_STYLE_DISPLAY_INLINE != display->mDisplay;
}
static nsIFrame*
@ -527,6 +525,27 @@ FindLastBlock(nsIPresContext* aPresContext, nsIFrame* aKid)
return lastBlock;
}
/*
* Unlike the special (next) sibling, the special previous sibling
* property points only from the anonymous block to the original inline
* that preceded it. It is useful for finding the "special parent" of a
* frame (i.e., a frame from which a good parent style context can be
* obtained), one looks at the special previous sibling annotation of
* the real parent of the frame (if the real parent has
* NS_FRAME_IS_SPECIAL).
*/
inline void
MarkIBSpecialPrevSibling(nsIPresContext* aPresContext,
nsIFrameManager *aFrameManager,
nsIFrame *aAnonymousFrame,
nsIFrame *aSpecialParent)
{
aFrameManager->SetFrameProperty(aAnonymousFrame,
nsLayoutAtoms::IBSplitSpecialPrevSibling,
aSpecialParent,
nsnull);
}
/**
* Moves frames to a new parent, updating the style context and
* propagating relevant frame state bits. |aNewParentSC| may be null,
@ -3803,7 +3822,9 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell,
if (NS_SUCCEEDED(rv)) {
// The placeholder frame gets a pseudo style context
nsCOMPtr<nsIStyleContext> placeholderStyle;
aPresContext->ResolveStyleContextForNonElement(aStyleContext, PR_FALSE,
nsCOMPtr<nsIStyleContext> parentContext =
dont_AddRef(aStyleContext->GetParent());
aPresContext->ResolveStyleContextForNonElement(parentContext, PR_FALSE,
getter_AddRefs(placeholderStyle));
placeholderFrame->Init(aPresContext, aContent, aParentFrame,
placeholderStyle, nsnull);
@ -9231,15 +9252,18 @@ DeletingFrameSubtree(nsIPresContext* aPresContext,
if (aFrameManager) {
nsAutoVoidArray destroyQueue;
while (aFrame) {
// If it's a "special" block-in-inline frame, then we need to
// remember to delete our special siblings, too.
if (IsFrameSpecial(aFrame)) {
nsIFrame* specialSibling;
GetSpecialSibling(aFrameManager, aFrame, &specialSibling);
DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager, specialSibling);
}
// If it's a "special" block-in-inline frame, then we need to
// remember to delete our special siblings, too. Since every one of
// the next-in-flows has the same special sibling, just do this
// once, rather than in the loop below.
if (IsFrameSpecial(aFrame)) {
nsIFrame* specialSibling;
GetSpecialSibling(aFrameManager, aFrame, &specialSibling);
DeletingFrameSubtree(aPresContext, aPresShell, aFrameManager,
specialSibling);
}
while (aFrame) {
DoDeletingFrameSubtree(aPresContext, aPresShell, aFrameManager,
destroyQueue, aFrame, aFrame);
@ -10483,9 +10507,15 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
nsIFrame* primaryFrame;
shell->GetPrimaryFrameFor(aContent, &primaryFrame);
// Get the frame associated with the content whose style context is highest in the style context tree
nsIFrame* primaryStyleFrame = nsnull;
nsIFrame* primaryStyleFrame = primaryFrame;
if (primaryFrame) {
primaryFrame->GetStyleContextProvider(aPresContext, &primaryStyleFrame);
PRBool providerIsChild = PR_FALSE;
nsIFrame *styleContextProvider;
primaryFrame->GetParentStyleContextFrame(aPresContext,
&styleContextProvider,
&providerIsChild);
if (providerIsChild)
primaryStyleFrame = styleContextProvider;
}
PRBool reconstruct = PR_FALSE;
@ -11220,6 +11250,8 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
lastBlock->SetNextSibling(nsnull);
// Create "special" inline-block linkage between the frames
// XXXldb Do we really need to do this? It doesn't seem
// consistent with the use in ConstructInline.
SetFrameIsSpecial(state.mFrameManager, list1, list2);
SetFrameIsSpecial(state.mFrameManager, list2, list3);
SetFrameIsSpecial(state.mFrameManager, list3, nsnull);
@ -13742,6 +13774,8 @@ nsCSSFrameConstructor::ConstructInline(nsIPresShell* aPresShell,
// containing block will be reframed instead.
SetFrameIsSpecial(aState.mFrameManager, aNewFrame, blockFrame);
SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame);
MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager,
blockFrame, aNewFrame);
if (inlineFrame)
SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull);
@ -14169,6 +14203,7 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext,
// Create an anonymous inline frame that will parent
// aRightInlineChildFrame. The new frame won't have a parent yet:
// the recursion will parent it.
// XXXldb Why bother if |aRightInlineChildFrame| is null?
nsIFrame* inlineFrame = nsnull;
NS_NewInlineFrame(shell, &inlineFrame);
if (! inlineFrame)
@ -14196,6 +14231,9 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsIPresContext* aPresContext,
SetFrameIsSpecial(aState.mFrameManager, blockFrame, inlineFrame);
SetFrameIsSpecial(aState.mFrameManager, inlineFrame, nsnull);
MarkIBSpecialPrevSibling(aPresContext, aState.mFrameManager,
blockFrame, firstInFlow);
// If we have a continuation frame, then we need to break the
// continuation.
nsIFrame* nextInFlow;

Просмотреть файл

@ -175,6 +175,19 @@ struct BCPropertyData
PRUint8 mLeftBorderWidth;
};
NS_IMETHODIMP
nsTableFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
// Since our parent, the table outer frame, returned this frame, we
// must return whatever our parent would normally have returned.
NS_PRECONDITION(mParent, "table constructed without outer table");
return NS_STATIC_CAST(nsFrame*, mParent)->
DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
}
NS_IMETHODIMP
nsTableFrame::GetFrameType(nsIAtom** aType) const

Просмотреть файл

@ -381,6 +381,10 @@ public:
nsFrameList& GetColGroups();
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
/**
* Get the "type" of the frame
*

Просмотреть файл

@ -414,20 +414,30 @@ NS_IMETHODIMP nsTableOuterFrame::SetSelected(nsIPresContext* aPresContext,
return result;
}
// GetStyleContextProvider:
// The innerTableFame is the style context provider, which is cached in a data member
NS_IMETHODIMP
nsTableOuterFrame::GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame)
nsTableOuterFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
NS_ASSERTION(aProviderFrame && aPresContext, "null argument: aPresContext and-or aProviderFrame");
if (aProviderFrame) {
if (mInnerTableFrame)
*aProviderFrame = mInnerTableFrame;
else
*aProviderFrame = this;
// The table outer frame and the (inner) table frame split the style
// data by giving the table frame the style context associated with
// the table content node and creating a style context for the outer
// frame that is a *child* of the table frame's style context,
// matching the :table-outer (should be :-moz-table-outer!)
// pseudo-element. html.css has a rule that causes that
// pseudo-element (and thus the outer table) to inherit *some* style
// properties from the table frame. The children of the table inherit
// directly from the inner table, and the outer table's style context
// is a leaf.
if (!mInnerTableFrame) {
*aProviderFrame = this;
*aIsChild = PR_FALSE;
return NS_ERROR_FAILURE;
}
return (aProviderFrame && mInnerTableFrame) ? NS_OK : NS_ERROR_FAILURE;
*aProviderFrame = mInnerTableFrame;
*aIsChild = PR_TRUE;
return NS_OK;
}
// INCREMENTAL REFLOW HELPER FUNCTIONS

Просмотреть файл

@ -171,8 +171,9 @@ public:
*/
nscoord GetMinCaptionWidth();
NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame);
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
/*---------------- nsITableLayout methods ------------------------*/

Просмотреть файл

@ -58,6 +58,7 @@
#include "nsRuleWalker.h"
#include "nsIHTMLDocument.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsHTMLAtoms.h"
#ifdef MOZ_PERF_METRICS
#include "nsITimeRecorder.h"
@ -1109,7 +1110,8 @@ nsIStyleContext* StyleSetImpl::ResolveStyleForNonElement(
mDocRuleProcessors ||
mOverrideRuleProcessors) {
EnsureRuleWalker(aPresContext);
result = GetContext(aPresContext, aParentContext, nsnull, aForceUnique);
result = GetContext(aPresContext, aParentContext,
nsHTMLAtoms::mozNonElementPseudo, aForceUnique);
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
}
}

Просмотреть файл

@ -175,6 +175,19 @@ struct BCPropertyData
PRUint8 mLeftBorderWidth;
};
NS_IMETHODIMP
nsTableFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
// Since our parent, the table outer frame, returned this frame, we
// must return whatever our parent would normally have returned.
NS_PRECONDITION(mParent, "table constructed without outer table");
return NS_STATIC_CAST(nsFrame*, mParent)->
DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
}
NS_IMETHODIMP
nsTableFrame::GetFrameType(nsIAtom** aType) const

Просмотреть файл

@ -381,6 +381,10 @@ public:
nsFrameList& GetColGroups();
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
/**
* Get the "type" of the frame
*

Просмотреть файл

@ -414,20 +414,30 @@ NS_IMETHODIMP nsTableOuterFrame::SetSelected(nsIPresContext* aPresContext,
return result;
}
// GetStyleContextProvider:
// The innerTableFame is the style context provider, which is cached in a data member
NS_IMETHODIMP
nsTableOuterFrame::GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame)
nsTableOuterFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild)
{
NS_ASSERTION(aProviderFrame && aPresContext, "null argument: aPresContext and-or aProviderFrame");
if (aProviderFrame) {
if (mInnerTableFrame)
*aProviderFrame = mInnerTableFrame;
else
*aProviderFrame = this;
// The table outer frame and the (inner) table frame split the style
// data by giving the table frame the style context associated with
// the table content node and creating a style context for the outer
// frame that is a *child* of the table frame's style context,
// matching the :table-outer (should be :-moz-table-outer!)
// pseudo-element. html.css has a rule that causes that
// pseudo-element (and thus the outer table) to inherit *some* style
// properties from the table frame. The children of the table inherit
// directly from the inner table, and the outer table's style context
// is a leaf.
if (!mInnerTableFrame) {
*aProviderFrame = this;
*aIsChild = PR_FALSE;
return NS_ERROR_FAILURE;
}
return (aProviderFrame && mInnerTableFrame) ? NS_OK : NS_ERROR_FAILURE;
*aProviderFrame = mInnerTableFrame;
*aIsChild = PR_TRUE;
return NS_OK;
}
// INCREMENTAL REFLOW HELPER FUNCTIONS

Просмотреть файл

@ -171,8 +171,9 @@ public:
*/
nscoord GetMinCaptionWidth();
NS_IMETHOD GetStyleContextProvider(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame);
NS_IMETHOD GetParentStyleContextFrame(nsIPresContext* aPresContext,
nsIFrame** aProviderFrame,
PRBool* aIsChild);
/*---------------- nsITableLayout methods ------------------------*/