Bug 500882 part 2. Switch setting of primary frames to the new API; switch nsFrameManager::GetPrimaryFrameFor to the new API; remove resulting gobs of dead code. r=roc

This commit is contained in:
Boris Zbarsky 2009-12-24 16:20:05 -05:00
Родитель f62bd5f370
Коммит 644c5ccda9
10 изменённых файлов: 94 добавлений и 528 удалений

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

@ -884,7 +884,11 @@ public:
* frame is the out of flow frame, not the placeholder.
*/
nsIFrame* GetPrimaryFrame() const { return mPrimaryFrame; }
void SetPrimaryFrame(nsIFrame* aFrame) { mPrimaryFrame = aFrame; }
void SetPrimaryFrame(nsIFrame* aFrame) {
NS_PRECONDITION(!aFrame || !mPrimaryFrame,
"Losing track of existing primary frame");
mPrimaryFrame = aFrame;
}
#ifdef MOZ_SMIL
/*

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

@ -239,7 +239,6 @@ nsIXBLService * nsCSSFrameConstructor::gXBLService = nsnull;
static PRBool gNoisyContentUpdates = PR_FALSE;
static PRBool gReallyNoisyContentUpdates = PR_FALSE;
static PRBool gNoisyInlineConstruction = PR_FALSE;
static PRBool gVerifyFastFindFrame = PR_FALSE;
struct FrameCtorDebugFlags {
const char* name;
@ -249,8 +248,7 @@ struct FrameCtorDebugFlags {
static FrameCtorDebugFlags gFlags[] = {
{ "content-updates", &gNoisyContentUpdates },
{ "really-noisy-content-updates", &gReallyNoisyContentUpdates },
{ "noisy-inline", &gNoisyInlineConstruction },
{ "fast-find-frame", &gVerifyFastFindFrame }
{ "noisy-inline", &gNoisyInlineConstruction }
};
#define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
@ -2489,7 +2487,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIContent* aDocEle
}
// set the primary frame
state.mFrameManager->SetPrimaryFrameFor(aDocElement, contentFrame);
aDocElement->SetPrimaryFrame(contentFrame);
NS_ASSERTION(processChildren ? !mRootElementFrame :
mRootElementFrame == contentFrame,
@ -3433,9 +3431,8 @@ nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
// Add the newly constructed frame to the flow
aFrameItems.AddChild(newFrame);
// Text frames don't go in the content->frame hash table, because
// they're anonymous. This keeps the hash table smaller
aContent->SetPrimaryFrame(newFrame);
return rv;
}
@ -3550,8 +3547,7 @@ nsCSSFrameConstructor::FindHTMLData(nsIContent* aContent,
SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
nsCSSFrameConstructor::FindImgData),
{ &nsGkAtoms::br,
FCDATA_DECL(FCDATA_SKIP_FRAMEMAP | FCDATA_IS_LINE_PARTICIPANT |
FCDATA_IS_LINE_BREAK,
FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_LINE_BREAK,
NS_NewBRFrame) },
SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame),
SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData),
@ -3747,9 +3743,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
display->IsScrollableOverflow()) {
BuildScrollFrame(aState, content, styleContext, newFrame,
geometricParent, frameToAddToList);
// No need to add to frame map later, since BuildScrollFrame did it
// already
bits |= FCDATA_SKIP_FRAMEMAP;
// No need to set the primary frame, since BuildScrollFrame did it already
bits |= FCDATA_SKIP_FRAMESET;
} else {
rv = InitAndRestoreFrame(aState, content, geometricParent, nsnull,
newFrame);
@ -3855,8 +3850,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
"Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
if (!(bits & FCDATA_SKIP_FRAMEMAP)) {
aState.mFrameManager->SetPrimaryFrameFor(aItem.mContent, newFrame);
if (!(bits & FCDATA_SKIP_FRAMESET)) {
aItem.mContent->SetPrimaryFrame(newFrame);
}
return NS_OK;
@ -4334,7 +4329,7 @@ nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState,
FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
// now set the primary frame to the ScrollFrame
aState.mFrameManager->SetPrimaryFrameFor( aContent, aNewFrame );
aContent->SetPrimaryFrame(aNewFrame);
return NS_OK;
}
@ -4394,56 +4389,50 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
// find them if we need to.
// XXXbz the "quickly" part is a bald-faced lie!
{ NS_STYLE_DISPLAY_INLINE,
FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP | FCDATA_IS_INLINE |
FCDATA_IS_LINE_PARTICIPANT,
FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
&nsCSSFrameConstructor::ConstructInline) },
{ NS_STYLE_DISPLAY_MARKER,
FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP | FCDATA_IS_INLINE |
FCDATA_IS_LINE_PARTICIPANT,
FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
&nsCSSFrameConstructor::ConstructInline) },
{ NS_STYLE_DISPLAY_TABLE,
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
{ NS_STYLE_DISPLAY_INLINE_TABLE,
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
{ NS_STYLE_DISPLAY_TABLE_CAPTION,
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_ALLOW_BLOCK_STYLES | FCDATA_DISALLOW_OUT_OF_FLOW |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_ALLOW_BLOCK_STYLES |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
NS_NewTableCaptionFrame) },
{ NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
NS_NewTableRowGroupFrame) },
{ NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
NS_NewTableRowGroupFrame) },
{ NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_MAY_NEED_SCROLLFRAME |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
NS_NewTableRowGroupFrame) },
{ NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
NS_NewTableColGroupFrame) },
{ NS_STYLE_DISPLAY_TABLE_COLUMN,
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
&nsCSSFrameConstructor::ConstructTableCol) },
{ NS_STYLE_DISPLAY_TABLE_ROW,
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
&nsCSSFrameConstructor::ConstructTableRow) },
{ NS_STYLE_DISPLAY_TABLE_CELL,
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
&nsCSSFrameConstructor::ConstructTableCell) }
};
@ -4644,8 +4633,7 @@ nsCSSFrameConstructor::FlushAccumulatedBlock(nsFrameConstructorState& aState,
{ &nsGkAtoms::_tag, \
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | \
FCDATA_FORCE_NULL_ABSPOS_CONTAINER | \
FCDATA_WRAP_KIDS_IN_BLOCKS | \
FCDATA_SKIP_FRAMEMAP, _func) }
FCDATA_WRAP_KIDS_IN_BLOCKS, _func) }
/* static */
const nsCSSFrameConstructor::FrameConstructionData*
@ -4663,17 +4651,14 @@ nsCSSFrameConstructor::FindMathMLData(nsIContent* aContent,
if (aStyleContext->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_BLOCK) {
static const FrameConstructionData sBlockMathData =
FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
FCDATA_WRAP_KIDS_IN_BLOCKS |
FCDATA_SKIP_FRAMEMAP,
FCDATA_WRAP_KIDS_IN_BLOCKS,
NS_CreateNewMathMLmathBlockFrame);
return &sBlockMathData;
}
static const FrameConstructionData sInlineMathData =
FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
FCDATA_WRAP_KIDS_IN_BLOCKS |
FCDATA_SKIP_FRAMEMAP |
FCDATA_IS_LINE_PARTICIPANT,
FCDATA_WRAP_KIDS_IN_BLOCKS,
NS_NewMathMLmathInlineFrame);
return &sInlineMathData;
}
@ -4718,7 +4703,7 @@ nsCSSFrameConstructor::FindMathMLData(nsIContent* aContent,
// should be in-flow.
#define SIMPLE_SVG_FCDATA(_func) \
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | \
FCDATA_SKIP_ABSPOS_PUSH | FCDATA_SKIP_FRAMEMAP | \
FCDATA_SKIP_ABSPOS_PUSH | \
FCDATA_DISALLOW_GENERATED_CONTENT, _func)
#define SIMPLE_SVG_CREATE(_tag, _func) \
{ &nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func) }
@ -4770,8 +4755,6 @@ nsCSSFrameConstructor::FindSVGData(nsIContent* aContent,
//
// Style mutation can't change this situation, so don't bother
// adding to the undisplayed content map.
// XXXbz except of course that this makes GetPrimaryFrameFor for this stuff
// that much slower.
//
// We don't currently handle any UI for desc/title
return &sSuppressData;
@ -4801,7 +4784,7 @@ nsCSSFrameConstructor::FindSVGData(nsIContent* aContent,
static const FrameConstructionData sOuterSVGData =
FCDATA_DECL(FCDATA_FORCE_VIEW | FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_SKIP_FRAMEMAP | FCDATA_DISALLOW_GENERATED_CONTENT,
FCDATA_DISALLOW_GENERATED_CONTENT,
NS_NewSVGOuterSVGFrame);
return &sOuterSVGData;
}
@ -4980,7 +4963,7 @@ nsCSSFrameConstructor::AddPageBreakItem(nsIContent* aContent,
NS_STYLE_DISPLAY_BLOCK, "Unexpected display");
static const FrameConstructionData sPageBreakData =
FCDATA_DECL(FCDATA_SKIP_FRAMEMAP, NS_NewPageBreakFrame);
FCDATA_DECL(FCDATA_SKIP_FRAMESET, NS_NewPageBreakFrame);
// Lie about the tag and namespace so we don't trigger anything
// interesting during frame construction.
@ -7486,8 +7469,8 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
"Reflow hint bits set without actually asking for a reflow");
if (frame && frame->GetContent() != content) {
// XXXbz this is due to image maps messing with the primary frame map.
// See bug 135040. Remove this block once that's fixed.
// XXXbz this is due to image maps messing with the primary frame of
// <area>s. See bug 135040. Remove this block once that's fixed.
frame = nsnull;
if (!(hint & nsChangeHint_ReconstructFrame)) {
continue;
@ -7576,8 +7559,8 @@ nsCSSFrameConstructor::RestyleElement(nsIContent *aContent,
NS_ASSERTION(aPrimaryFrame == mPresShell->GetPrimaryFrameFor(aContent),
"frame/content mismatch");
if (aPrimaryFrame && aPrimaryFrame->GetContent() != aContent) {
// XXXbz this is due to image maps messing with the primary frame mapping.
// See bug 135040. We can remove this block once that's fixed.
// XXXbz this is due to image maps messing with the primary frame pointer
// of <area>s. See bug 135040. We can remove this block once that's fixed.
aPrimaryFrame = nsnull;
}
NS_ASSERTION(!aPrimaryFrame || aPrimaryFrame->GetContent() == aContent,
@ -8290,251 +8273,6 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
return NS_OK;
}
static PRBool
IsBindingAncestor(nsIContent* aContent, nsIContent* aBindingRoot)
{
while (PR_TRUE) {
// Native-anonymous content doesn't contain insertion points, so
// we don't need to search through it.
if (aContent->IsRootOfNativeAnonymousSubtree())
return PR_FALSE;
nsIContent* bindingParent = aContent->GetBindingParent();
if (!bindingParent)
return PR_FALSE;
if (bindingParent == aBindingRoot)
return PR_TRUE;
aContent = bindingParent;
}
}
// Helper function that searches the immediate child frames
// (and their children if the frames are "special")
// for a frame that maps the specified content object
nsIFrame*
nsCSSFrameConstructor::FindFrameWithContent(nsFrameManager* aFrameManager,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent,
nsFindFrameHint* aHint)
{
NS_PRECONDITION(aParentFrame, "Must have a frame");
#ifdef NOISY_FINDFRAME
FFWC_totalCount++;
printf("looking for content=%p, given aParentFrame %p parentContent %p, hint is %s\n",
aContent, aParentFrame, aParentContent, aHint ? "set" : "NULL");
#endif
// Search for the frame in each child list that aParentFrame supports.
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
PRBool searchAgain;
do {
#ifdef NOISY_FINDFRAME
FFWC_doLoop++;
#endif
nsIFrame* kidFrame = nsnull;
searchAgain = PR_FALSE;
// if we were given an hint, try to use it here to find a good
// previous frame to start our search (|kidFrame|).
if (aHint) {
#ifdef NOISY_FINDFRAME
printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling);
#endif
// start with the primary frame for aContent's previous sibling
kidFrame = aHint->mPrimaryFrameForPrevSibling;
// But if it's out of flow, start from its placeholder.
if (kidFrame && (kidFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
kidFrame = aFrameManager->GetPlaceholderFrameFor(kidFrame);
}
if (kidFrame) {
// then use the next sibling frame as our starting point
if (kidFrame->GetNextSibling()) {
kidFrame = kidFrame->GetNextSibling();
}
else {
// The hint frame had no next sibling. Try the next-in-flow or
// special sibling of the parent of the hint frame (or its
// associated placeholder).
nsIFrame *parentFrame = kidFrame->GetParent();
kidFrame = nsnull;
if (parentFrame) {
parentFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(parentFrame);
}
if (parentFrame) {
// Found it, continue the search with its first child.
kidFrame = parentFrame->GetFirstChild(listName);
// Leave |aParentFrame| as-is, since the only time we'll
// reuse it is if the hint fails.
}
}
#ifdef NOISY_FINDFRAME
printf(" hint gives us kidFrame=%p with parent frame %p content %p\n",
kidFrame, aParentFrame, aParentContent);
#endif
}
}
if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning
kidFrame = aParentFrame->GetFirstChild(listName);
}
while (kidFrame) {
// See if the child frame points to the content object we're
// looking for
nsIContent* kidContent = kidFrame->GetContent();
if (kidContent == aContent) {
// We found a match. Return the out-of-flow if it's a placeholder.
return nsPlaceholderFrame::GetRealFrameFor(kidFrame);
}
// only do this if there is content
if (kidContent) {
// We search the immediate children only, but if the child frame has
// the same content pointer as its parent then we need to search its
// child frames, too.
// We also need to search if the child content is anonymous and scoped
// to the parent content.
// XXXldb What makes us continue the search once we're inside
// the anonymous subtree?
if (aParentContent == kidContent ||
(aParentContent && IsBindingAncestor(kidContent, aParentContent))) {
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, aParentContent);
#endif
nsIFrame* matchingFrame =
FindFrameWithContent(aFrameManager,
nsPlaceholderFrame::GetRealFrameFor(kidFrame),
aParentContent, aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
}
}
}
kidFrame = kidFrame->GetNextSibling();
#ifdef NOISY_FINDFRAME
if (kidFrame) {
FFWC_doSibling++;
printf(" searching sibling frame %p\n", kidFrame);
}
#endif
}
if (aHint) {
// If we get here, and we had a hint, then we didn't find a frame.
// The hint may have been a frame whose location in the frame tree
// doesn't match the location of its corresponding element in the
// DOM tree, e.g. a floated or absolutely positioned frame, or e.g.
// a <col> frame, in which case we'd be off in the weeds looking
// through something other than the primary frame list.
// Reboot the search from scratch, without the hint, but using the
// null child list again.
aHint = nsnull;
searchAgain = PR_TRUE;
}
else {
do {
listName = aParentFrame->GetAdditionalChildListName(listIndex++);
} while (IsOutOfFlowList(listName));
}
} while (listName || searchAgain);
return nsnull;
}
// Request to find the primary frame associated with a given content object.
// This is typically called by the pres shell when there is no mapping in
// the pres shell hash table
nsresult
nsCSSFrameConstructor::FindPrimaryFrameFor(nsFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame,
nsFindFrameHint* aHint)
{
NS_ASSERTION(aFrameManager && aContent && aFrame, "bad arg");
*aFrame = nsnull; // initialize OUT parameter
// We want to be able to quickly map from a content object to its frame,
// but we also want to keep the hash table small. Therefore, many frames
// are not added to the hash table when they're first created:
// - text frames
// - inline frames (often things like FONT and B)
// - BR frames
// - internal table frames (row-group, row, cell, col-group, col)
//
// That means we need to need to search for the frame
nsIFrame* parentFrame; // this pointer is used to iterate across all frames that map to parentContent
// Get the frame that corresponds to the parent content object.
// Note that this may recurse indirectly, because the pres shell will
// call us back if there is no mapping in the hash table
nsCOMPtr<nsIContent> parentContent = aContent->GetParent(); // Get this once
if (parentContent) {
parentFrame = aFrameManager->GetPrimaryFrameFor(parentContent, -1);
while (parentFrame) {
// Search the child frames for a match
*aFrame = FindFrameWithContent(aFrameManager, parentFrame,
parentContent, aContent, aHint);
#ifdef NOISY_FINDFRAME
printf("FindFrameWithContent returned %p\n", *aFrame);
#endif
#ifdef DEBUG
// if we're given a hint and we were told to verify, then compare the resulting frame with
// the frame we get by calling FindFrameWithContent *without* the hint.
// Assert if they do not match
// Note that this makes finding frames *slower* than it was before the fix.
if (gVerifyFastFindFrame && aHint) {
#ifdef NOISY_FINDFRAME
printf("VERIFYING...\n");
#endif
nsIFrame *verifyTestFrame =
FindFrameWithContent(aFrameManager, parentFrame,
parentContent, aContent, nsnull);
#ifdef NOISY_FINDFRAME
printf("VERIFY returned %p\n", verifyTestFrame);
#endif
NS_ASSERTION(verifyTestFrame == *aFrame, "hint shortcut found wrong frame");
}
#endif
// If we found a match, then add a mapping to the hash table so
// next time this will be quick
if (*aFrame) {
aFrameManager->SetPrimaryFrameFor(aContent, *aFrame);
break;
}
// We didn't find a matching frame. If parentFrame has a next-in-flow
// or special sibling, then continue looking there.
parentFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(parentFrame);
#ifdef NOISY_FINDFRAME
if (parentFrame) {
FFWC_nextInFlows++;
printf(" searching NIF frame %p\n", parentFrame);
}
#endif
}
}
#ifdef NOISY_FINDFRAME
printf("%10s %10s %10s %10s %10s\n",
"total", "doLoop", "doSibling", "recur", "nextIF");
printf("%10d %10d %10d %10d %10d\n",
FFWC_totalCount, FFWC_doLoop, FFWC_doSibling, FFWC_recursions,
FFWC_nextInFlows);
#endif
return NS_OK;
}
nsresult
nsCSSFrameConstructor::GetInsertionPoint(nsIFrame* aParentFrame,
nsIContent* aChildContent,
@ -8980,21 +8718,21 @@ nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(nsIContent* aContent,
const nsCSSFrameConstructor::PseudoParentData
nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
{ // Cell
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
FCDATA_USE_CHILD_ITEMS |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
&nsCSSFrameConstructor::ConstructTableCell),
&nsCSSAnonBoxes::tableCell
},
{ // Row
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
FCDATA_USE_CHILD_ITEMS |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
&nsCSSFrameConstructor::ConstructTableRow),
&nsCSSAnonBoxes::tableRow
},
{ // Row group
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
@ -9002,7 +8740,7 @@ nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
&nsCSSAnonBoxes::tableRowGroup
},
{ // Column group
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMEMAP |
FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
FCDATA_SKIP_ABSPOS_PUSH |
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
@ -9010,7 +8748,7 @@ nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
&nsCSSAnonBoxes::tableColGroup
},
{ // Table
FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMEMAP | FCDATA_USE_CHILD_ITEMS,
FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
&nsCSSFrameConstructor::ConstructTable),
&nsCSSAnonBoxes::table
}
@ -9907,6 +9645,7 @@ nsCSSFrameConstructor::CreateLetterFrame(nsIFrame* aBlockFrame,
aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
}
}
aTextContent->SetPrimaryFrame(textFrame);
}
return NS_OK;
@ -10084,6 +9823,7 @@ nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
return NS_ERROR_OUT_OF_MEMORY;;
}
newTextFrame->Init(textContent, parentFrame, nsnull);
textContent->SetPrimaryFrame(newTextFrame);
// Destroy the old text frame's continuations (the old text frame
// will be destroyed when its letter frame is destroyed).
@ -10146,6 +9886,7 @@ nsCSSFrameConstructor::RemoveFirstLetterFrames(nsPresContext* aPresContext,
}
textFrame = NS_NewTextFrame(aPresShell, newSC);
textFrame->Init(textContent, aFrame, nsnull);
textContent->SetPrimaryFrame(textFrame);
// Next rip out the kid and replace it with the text frame
aFrameManager->RemoveFrame(nsnull, kid);

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

@ -72,12 +72,6 @@ class nsICSSAnonBoxPseudo;
class nsPageContentFrame;
struct PendingBinding;
struct nsFindFrameHint
{
nsIFrame *mPrimaryFrameForPrevSibling; // weak ref to the primary frame for the content for which we need a frame
nsFindFrameHint() : mPrimaryFrameForPrevSibling(nsnull) { }
};
typedef void (nsLazyFrameConstructionCallback)
(nsIContent* aContent, nsIFrame* aFrame, void* aArg);
@ -286,14 +280,6 @@ public:
// Copy over fixed frames from aParentFrame's prev-in-flow
nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
// Request to find the primary frame associated with a given content object.
// This is typically called by the pres shell when there is no mapping in
// the pres shell hash table
nsresult FindPrimaryFrameFor(nsFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame,
nsFindFrameHint* aHint);
// Get the XBL insertion point for a child
nsresult GetInsertionPoint(nsIFrame* aParentFrame,
nsIContent* aChildContent,
@ -337,6 +323,7 @@ private:
PRInt32 aStateMask);
/* aMinHint is the minimal change that should be made to the element */
// XXXbz do we really need the aPrimaryFrame argument here?
void RestyleElement(nsIContent* aContent,
nsIFrame* aPrimaryFrame,
nsChangeHint aMinHint);
@ -551,7 +538,7 @@ private:
not the thing that ends up in aFrameItems? If not, would it be safe to do
the add into the frame construction state after processing kids? Look
into this as a followup!), process children as needed, etc. It is NOT
expected to deal with the primary frame map.
expected to deal with setting the frame on the content.
@param aState the frame construction state to use.
@param aItem the frame construction item to use
@ -561,7 +548,7 @@ private:
@param aFrameItems the frame list to add the new frame (or its
placeholder) to.
@param aFrame out param handing out the frame that was constructed. This
frame is what the caller will add to the primary frame map.
frame is what the caller will set as the frame on the content.
*/
typedef nsresult
(nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
@ -573,11 +560,11 @@ private:
/* Bits that modify the way a FrameConstructionData is handled */
/* If the FCDATA_SKIP_FRAMEMAP bit is set, then the frame created should not
be added to the primary frame map. This flag might get ignored when used
with FCDATA_MAY_NEED_SCROLLFRAME, since scrollframe construction will add
to the frame map. */
#define FCDATA_SKIP_FRAMEMAP 0x1
/* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
be set as the primary frame on the content node. This should only be used
in very rare cases when we create more than one frame for a given content
node. */
#define FCDATA_SKIP_FRAMESET 0x1
/* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
FrameConstructionData is a getter function that can be used to get the
actual FrameConstructionData to use. */
@ -1129,8 +1116,8 @@ private:
FindObjectData(nsIContent* aContent, nsStyleContext* aStyleContext);
/* Construct a frame from the given FrameConstructionItem. This function
will handle adding the frame to frame lists, processing children, adding
it to the primary frame map, and so forth.
will handle adding the frame to frame lists, processing children, setting
the frame as the primary frame for the item's content, and so forth.
@param aItem the FrameConstructionItem to use.
@param aState the frame construction state to use.
@ -1393,10 +1380,11 @@ private:
// containing block (either of aFrame or of its parent) due to {ib} splits or
// table pseudo-frames, recreate the relevant frame subtree. The return value
// indicates whether this happened. If this method returns true, *aResult is
// the return value of ReframeContainingBlock or RecreateFramesForContent.
// If this method returns false, the value of *aResult is not affected.
// aFrame and aResult must not be null. aFrame must be the result of a
// GetPrimaryFrameFor() call (which means its parent is also not null).
// the return value of ReframeContainingBlock or RecreateFramesForContent. If
// this method returns false, the value of *aResult is not affected. aFrame
// and aResult must not be null. aFrame must be the result of a
// GetPrimaryFrame() call on a content node (which means its parent is also
// not null).
PRBool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
nsresult* aResult);
@ -1526,21 +1514,6 @@ private:
nsresult StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint);
/** Helper function that searches the immediate child frames
* (and their children if the frames are "special")
* for a frame that maps the specified content object
*
* @param aParentFrame the primary frame for aParentContent
* @param aContent the content node for which we seek a frame
* @param aParentContent the parent for aContent
* @param aHint an optional hint used to make the search for aFrame faster
*/
nsIFrame* FindFrameWithContent(nsFrameManager* aFrameManager,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent,
nsFindFrameHint* aHint);
//----------------------------------------
// Methods support :first-letter style

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

@ -150,41 +150,6 @@ static PLDHashTableOps PlaceholderMapOps = {
//----------------------------------------------------------------------
struct PrimaryFrameMapEntry : public PLDHashEntryHdr {
// key (the content node) can almost always be obtained through the
// frame. If it weren't for the way image maps (mis)used the primary
// frame map, we'd be able to have a 2 word entry instead of a 3 word
// entry.
nsIContent *content;
nsIFrame *frame;
};
// These ops should be used if/when we switch back to a 2-word entry.
// See comment in |PrimaryFrameMapEntry| above.
#if 0
static PRBool
PrimaryFrameMapMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
const void *key)
{
const PrimaryFrameMapEntry *entry =
static_cast<const PrimaryFrameMapEntry*>(hdr);
return entry->frame->GetContent() == key;
}
static PLDHashTableOps PrimaryFrameMapOps = {
PL_DHashAllocTable,
PL_DHashFreeTable,
PL_DHashVoidPtrKeyStub,
PrimaryFrameMapMatchEntry,
PL_DHashMoveEntryStub,
PL_DHashClearEntryStub,
PL_DHashFinalizeStub,
NULL
};
#endif /* 0 */
//----------------------------------------------------------------------
// XXXldb This seems too complicated for what I think it's doing, and it
// should also be using pldhash rather than plhash to use less memory.
@ -292,7 +257,6 @@ nsFrameManager::Destroy()
mRootFrame = nsnull;
}
nsFrameManager::ClearPrimaryFrameMap();
delete mUndisplayedMap;
mUndisplayedMap = nsnull;
@ -340,145 +304,19 @@ nsFrameManager::GetPrimaryFrameFor(nsIContent* aContent,
return nsnull;
}
if (!aContent->MayHaveFrame()) {
if (aContent->GetCurrentDoc() != mPresShell->GetDocument()) {
return nsnull;
}
if (mPrimaryFrameMap.ops) {
PrimaryFrameMapEntry *entry = static_cast<PrimaryFrameMapEntry*>
(PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
return entry->frame;
}
// XXX: todo: Add a lookup into the undisplay map to skip searches
// if we already know the content has no frame.
// nsCSSFrameConstructor calls SetUndisplayedContent() for every
// content node that has display: none.
// Today, the undisplay map doesn't quite support what we need.
// We need to see if we can add a method to make a search for aContent
// very fast in the embedded hash table.
// This would almost completely remove the lookup penalty for things
// like <SCRIPT> and comments in very large documents.
// XXX with the nsIContent::MayHaveFrame bit, is that really necessary now?
// Give the frame construction code the opportunity to return the
// frame that maps the content object
// if the prev sibling of aContent has a cached primary frame,
// pass that data in to the style set to speed things up
// if any methods in here fail, don't report that failure
// we're just trying to enhance performance here, not test for correctness
nsFindFrameHint hint;
nsIContent* parent = aContent->GetParent();
if (parent)
{
PRInt32 index = aIndexHint >= 0 ? aIndexHint : parent->IndexOf(aContent);
if (index > 0) // no use looking if it's the first child
{
nsIContent *prevSibling;
do {
prevSibling = parent->GetChildAt(--index);
} while (index &&
(prevSibling->IsNodeOfType(nsINode::eTEXT) ||
prevSibling->IsNodeOfType(nsINode::eCOMMENT) ||
prevSibling->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)));
if (prevSibling) {
entry = static_cast<PrimaryFrameMapEntry*>
(PL_DHashTableOperate(&mPrimaryFrameMap, prevSibling,
PL_DHASH_LOOKUP));
// XXXbz the GetContent() == prevSibling check is needed due to bug
// 135040. Remove it once that's fixed.
if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->frame &&
entry->frame->GetContent() == prevSibling)
hint.mPrimaryFrameForPrevSibling = entry->frame;
}
}
}
// walk the frame tree to find the frame that maps aContent.
// Use the hint if we have it.
nsIFrame *result;
mPresShell->FrameConstructor()->
FindPrimaryFrameFor(this, aContent, &result,
hint.mPrimaryFrameForPrevSibling ? &hint : nsnull);
return result;
}
return nsnull;
}
nsresult
nsFrameManager::SetPrimaryFrameFor(nsIContent* aContent,
nsIFrame* aPrimaryFrame)
{
NS_ENSURE_ARG_POINTER(aContent);
NS_ASSERTION(aPrimaryFrame && aPrimaryFrame->GetParent(),
"BOGUS!");
#ifdef DEBUG
{
nsIFrame *docElementCB =
mPresShell->FrameConstructor()->GetDocElementContainingBlock();
NS_ASSERTION(aPrimaryFrame != docElementCB &&
!nsLayoutUtils::IsProperAncestorFrame(aPrimaryFrame,
docElementCB),
"too high in the frame tree to be a primary frame");
}
#endif
// This code should be used if/when we switch back to a 2-word entry
// in the primary frame map.
#if 0
NS_PRECONDITION(aPrimaryFrame->GetContent() == aContent, "wrong content");
#endif
// Create a new hashtable if necessary
if (!mPrimaryFrameMap.ops) {
if (!PL_DHashTableInit(&mPrimaryFrameMap, PL_DHashGetStubOps(), nsnull,
sizeof(PrimaryFrameMapEntry), 16)) {
mPrimaryFrameMap.ops = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
}
// Add a mapping to the hash table
PrimaryFrameMapEntry *entry = static_cast<PrimaryFrameMapEntry*>
(PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_ADD));
#ifdef DEBUG_dbaron
if (entry->frame) {
NS_WARNING("already have primary frame for content");
}
#endif
entry->frame = aPrimaryFrame;
entry->content = aContent;
return NS_OK;
return aContent->GetPrimaryFrame();
}
void
nsFrameManager::RemoveAsPrimaryFrame(nsIContent* aContent,
nsIFrame* aPrimaryFrame)
{
NS_PRECONDITION(aPrimaryFrame, "Must have a frame");
if (aContent && mPrimaryFrameMap.ops) {
PrimaryFrameMapEntry *entry = static_cast<PrimaryFrameMapEntry*>
(PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->frame == aPrimaryFrame) {
// Don't use PL_DHashTableRawRemove, since we want the table to
// shrink as needed.
PL_DHashTableOperate(&mPrimaryFrameMap, aContent, PL_DHASH_REMOVE);
}
}
}
void
nsFrameManager::ClearPrimaryFrameMap()
{
if (mPrimaryFrameMap.ops) {
PL_DHashTableFinish(&mPrimaryFrameMap);
mPrimaryFrameMap.ops = nsnull;
if (aContent->GetPrimaryFrame() == aPrimaryFrame) {
aContent->SetPrimaryFrame(nsnull);
}
}

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

@ -110,20 +110,12 @@ public:
NS_HIDDEN_(nsIFrame*) GetCanvasFrame();
// Primary frame functions
// If aIndexHint it not -1, it will be used as when determining a frame hint
// instead of calling IndexOf(aContent).
NS_HIDDEN_(nsIFrame*) GetPrimaryFrameFor(nsIContent* aContent,
PRInt32 aIndexHint);
// aPrimaryFrame must not be null. If you're trying to remove a primary frame
// mapping, use RemoveAsPrimaryFrame.
NS_HIDDEN_(nsresult) SetPrimaryFrameFor(nsIContent* aContent,
nsIFrame* aPrimaryFrame);
// If aPrimaryFrame is the current primary frame for aContent, remove the
// relevant hashtable entry. If the current primary frame for aContent is
// null, this does nothing. aPrimaryFrame must not be null.
// If aPrimaryFrame is the current primary frame for aContent, set its
// primary frame to null. aPrimaryFrame must not be null.
NS_HIDDEN_(void) RemoveAsPrimaryFrame(nsIContent* aContent,
nsIFrame* aPrimaryFrame);
NS_HIDDEN_(void) ClearPrimaryFrameMap();
// Placeholder frame functions
NS_HIDDEN_(nsPlaceholderFrame*) GetPlaceholderFrameFor(nsIFrame* aFrame);

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

@ -72,6 +72,7 @@
#include "nsContentUtils.h"
#include "nsIWidget.h"
#include "mozilla/TimeStamp.h"
#include "nsIContent.h"
class nsImageLoader;
#ifdef IBMBIDI
@ -82,7 +83,6 @@ struct nsRect;
class imgIRequest;
class nsIContent;
class nsIFontMetrics;
class nsIFrame;
class nsFrameManager;
@ -904,6 +904,22 @@ public:
*/
void SMILOverrideStyleChanged(nsIContent* aContent);
#endif // MOZ_SMIL
/**
* If we have a presshell, and if the given content's current
* document is the same as our presshell's document, return the
* content's primary frame. Otherwise, return null. Only use this
* if you care about which presshell the primary frame is in.
*/
nsIFrame* GetPrimaryFrameFor(nsIContent* aContent) {
NS_PRECONDITION(aContent, "Don't do that");
if (GetPresShell() &&
GetPresShell()->GetDocument() == aContent->GetCurrentDoc()) {
return aContent->GetPrimaryFrame();
}
return nsnull;
}
protected:
friend class nsRunnableMethod<nsPresContext>;
NS_HIDDEN_(void) ThemeChangedInternal();

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

@ -339,8 +339,6 @@ nsFrame::Init(nsIContent* aContent,
if (aContent) {
NS_ADDREF(aContent);
aContent->SetMayHaveFrame(PR_TRUE);
NS_ASSERTION(mContent->MayHaveFrame(), "SetMayHaveFrame failed?");
}
if (aPrevInFlow) {
@ -466,6 +464,11 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
view->Destroy();
}
// Make sure that our deleted frame can't be returned from GetPrimaryFrame()
if (mContent && mContent->GetPrimaryFrame() == this) {
mContent->SetPrimaryFrame(nsnull);
}
// Must retrieve the object ID before calling destructors, so the
// vtable is still valid.
//

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

@ -284,7 +284,7 @@ nsSubDocumentFrame::Init(nsIContent* aContent,
// Set the primary frame now so that
// DocumentViewerImpl::FindContainerView called by ShowViewer below
// can find it if necessary.
PresContext()->FrameManager()->SetPrimaryFrameFor(aContent, this);
aContent->SetPrimaryFrame(this);
ShowViewer();
return NS_OK;

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

@ -414,6 +414,7 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent,
mChildFrameborder[mChildCount] = GetFrameBorder(child);
mChildBorderColors[mChildCount].Set(GetBorderColor(child));
}
child->SetPrimaryFrame(frame);
if (NS_FAILED(result))
return result;

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

@ -900,9 +900,7 @@ nsImageMap::AddArea(nsIContent* aArea)
// nsCSSFrameConstructor::ContentRemoved (both hacks there), and
// nsCSSFrameConstructor::ProcessRestyledFrames to work around this issue can
// be removed.
mPresShell->FrameManager()->SetPrimaryFrameFor(aArea, mImageFrame);
aArea->SetMayHaveFrame(PR_TRUE);
NS_ASSERTION(aArea->MayHaveFrame(), "SetMayHaveFrame failed?");
aArea->SetPrimaryFrame(mImageFrame);
area->ParseCoords(coords);
mAreas.AppendElement(area);