Clean up FindFrameWithContent. No need to search children of special frames too (hang bug 140275). Use special sibling when next-in-flow isn't available, and use the hint even when we have special frames. Convert gotos into additional while loop. Turn useless :after check into assertion. Don't modify aParentFrame and aParentContent for when the hint fails. b=140275 r=attinasi sr=waterson

This commit is contained in:
dbaron%fas.harvard.edu 2002-05-16 13:39:44 +00:00
Родитель a2dc0c286f
Коммит 015b68bde1
4 изменённых файлов: 282 добавлений и 282 удалений

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

@ -3204,15 +3204,6 @@ nsCSSFrameConstructor::ConstructDocElementTableFrame(nsIPresShell* aPresS
return NS_OK; return NS_OK;
} }
static PRBool
IsCanvasFrame(nsIFrame* aFrame)
{
nsCOMPtr<nsIAtom> parentType;
aFrame->GetFrameType(getter_AddRefs(parentType));
return parentType.get() == nsLayoutAtoms::canvasFrame;
}
/** /**
* New one * New one
*/ */
@ -11748,14 +11739,30 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsIPresShell* aPresShell,
return rv; return rv;
} }
// Get the frame's next-in-flow, or, if it doesn't have one,
// its special sibling.
static nsIFrame*
GetNifOrSpecialSibling(nsIFrameManager *aFrameManager, nsIFrame *aFrame)
{
nsIFrame *result;
aFrame->GetNextInFlow(&result);
if (result)
return result;
if (IsFrameSpecial(aFrame))
GetSpecialSibling(aFrameManager, aFrame, &result);
return result;
}
// Helper function that searches the immediate child frames // Helper function that searches the immediate child frames
// (and their children if the frames are "special") // (and their children if the frames are "special")
// for a frame that maps the specified content object // for a frame that maps the specified content object
nsIFrame* nsIFrame*
nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext, nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame, nsIFrameManager* aFrameManager,
nsIContent* aParentContent, nsIFrame* aParentFrame,
nsIContent* aContent, nsIContent* aParentContent,
nsIContent* aContent,
nsFindFrameHint* aHint) nsFindFrameHint* aHint)
{ {
@ -11765,29 +11772,20 @@ nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext,
aContent, aParentFrame, aParentContent, aHint ? "set" : "NULL"); aContent, aParentFrame, aParentContent, aHint ? "set" : "NULL");
#endif #endif
NS_PRECONDITION(aParentFrame, "No frame to search!"); NS_ENSURE_TRUE(aParentFrame != nsnull, nsnull);
if (!aParentFrame) {
return nsnull;
}
nsCOMPtr<nsIContent> parentContent = aParentContent; // because we might change this when using the hint
PRBool firstTime = PR_TRUE; // marker to let us know to only use aHint the very first time through
// must be declared outside loop and above goto label "keepLooking"
keepLooking:
// Search for the frame in each child list that aParentFrame supports
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
do { do {
// Search for the frame in each child list that aParentFrame supports
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
do {
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
FFWC_doLoop++; FFWC_doLoop++;
#endif #endif
nsIFrame* kidFrame=nsnull; nsIFrame* kidFrame=nsnull;
if (aHint && firstTime) // if we were given an hint, try to use it here to find a good
{ // if we were given an hint, try to use it here, unless the parent frame is special // previous frame to start our search (|kidFrame|).
if (!IsFrameSpecial(aParentFrame)) if (aHint) {
{
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling); printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling);
#endif #endif
@ -11800,141 +11798,138 @@ keepLooking:
nsIFrame *parentFrame=nsnull; nsIFrame *parentFrame=nsnull;
aHint->mPrimaryFrameForPrevSibling->GetParent(&parentFrame); aHint->mPrimaryFrameForPrevSibling->GetParent(&parentFrame);
if (parentFrame) { if (parentFrame) {
parentFrame->GetNextInFlow(&parentFrame); parentFrame = GetNifOrSpecialSibling(aFrameManager, parentFrame);
} }
if (parentFrame) if (parentFrame)
{ // if we found the next-in-flow for the parent of the hint frame, start with it's first child { // if we found the next-in-flow for the parent of the hint frame, start with it's first child
parentFrame->FirstChild(aPresContext, listName, &kidFrame); parentFrame->FirstChild(aPresContext, listName, &kidFrame);
if (kidFrame) // Leave |aParentFrame| as-is, since the only time we'll
{ // reuse it is if the hint fails.
aParentFrame = parentFrame; // if we found a match, make this the new starting point #ifdef DEBUG
aParentFrame->GetContent(getter_AddRefs(parentContent)); if (kidFrame) {
nsCOMPtr<nsIContent> parentContent;
parentFrame->GetContent(getter_AddRefs(parentContent));
NS_ASSERTION(parentContent == aParentContent,
"next-in-flow has different content");
} }
#endif
} }
} }
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf(" hint gives us kidFrame=%p with parent frame %p content %p\n", printf(" hint gives us kidFrame=%p with parent frame %p content %p\n",
kidFrame, aParentFrame, parentContent); kidFrame, aParentFrame, aParentContent);
#endif #endif
} }
} }
else if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning
{ aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
#ifdef NOISY_FINDFRAME
printf("skipping hint because parent frame is special\n");
#endif
} }
} while (kidFrame) {
if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning nsCOMPtr<nsIContent> kidContent;
aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
} // See if the child frame points to the content object we're
while (kidFrame) { // looking for
nsCOMPtr<nsIContent> kidContent; kidFrame->GetContent(getter_AddRefs(kidContent));
if (kidContent == aContent) {
// See if the child frame points to the content object we're nsCOMPtr<nsIAtom> frameType;
// looking for
kidFrame->GetContent(getter_AddRefs(kidContent));
if (kidContent.get() == aContent) {
nsCOMPtr<nsIAtom> frameType;
// We found a match. See if it's a placeholder frame // We found a match. See if it's a placeholder frame
kidFrame->GetFrameType(getter_AddRefs(frameType)); kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::placeholderFrame == frameType.get()) { if (nsLayoutAtoms::placeholderFrame == frameType.get()) {
// Ignore the placeholder and return the out-of-flow frame instead // Ignore the placeholder and return the out-of-flow frame instead
return ((nsPlaceholderFrame*)kidFrame)->GetOutOfFlowFrame(); return ((nsPlaceholderFrame*)kidFrame)->GetOutOfFlowFrame();
} else { } else {
// Check if kidframe is the :before pseudo frame for aContent. If it // Check if kidframe is the :before pseudo frame for aContent. If it
// is, and aContent is an element, then aContent might be a // is, and aContent is an element, then aContent might be a
// non-splittable-element, so the real primary frame could be the // non-splittable-element, so the real primary frame could be the
// next sibling. // next sibling.
if (aContent->IsContentOfType(nsIContent::eELEMENT) && if (aContent->IsContentOfType(nsIContent::eELEMENT) &&
IsGeneratedContentFor(aContent, kidFrame, nsCSSAtoms::beforePseudo)) { IsGeneratedContentFor(aContent, kidFrame, nsCSSAtoms::beforePseudo)) {
nsIFrame *nextSibling = nsnull; kidFrame->GetNextSibling(&kidFrame);
#ifdef DEBUG
NS_ASSERTION(kidFrame, ":before with no next sibling");
if (kidFrame) {
nsCOMPtr<nsIContent> nextSiblingContent;
kidFrame->GetContent(getter_AddRefs(nextSiblingContent));
kidFrame->GetNextSibling(&nextSibling); // Make sure the content matches, and because I'm paranoid,
if (nextSibling) { // make sure it's not the :after pseudo frame.
nsCOMPtr<nsIContent> nextSiblingContent;
nextSibling->GetContent(getter_AddRefs(nextSiblingContent));
// Make sure the content matches, and because I'm paranoid, NS_ASSERTION(nextSiblingContent.get() == aContent &&
// make sure it's not the :after pseudo frame. !IsGeneratedContentFor(aContent, kidFrame,
nsCSSAtoms::afterPseudo),
":before frame not followed by primary frame");
}
#endif
}
if (nextSiblingContent.get() == aContent && // Return the matching child frame
!IsGeneratedContentFor(aContent, nextSibling, nsCSSAtoms::afterPseudo)) return kidFrame;
kidFrame = nextSibling; }
}
// 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.
nsCOMPtr<nsIContent> parentScope;
kidContent->GetBindingParent(getter_AddRefs(parentScope));
if (aParentContent == kidContent ||
(aParentContent && (aParentContent == parentScope)))
{
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, aParentContent.get());
#endif
nsIFrame* matchingFrame =
FindFrameWithContent(aPresContext, aFrameManager, kidFrame,
aParentContent, aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
} }
} }
// Return the matching child frame
return kidFrame;
} }
}
// only do this if there is content // Get the next sibling frame
if (kidContent) { kidFrame->GetNextSibling(&kidFrame);
// We search the immediate children only, but if the child frame has #ifdef NOISY_FINDFRAME
// the same content pointer as its parent then we need to search its FFWC_doSibling++;
// child frames, too. if (kidFrame) {
// We also need to search the child frame's children if the child frame printf(" searching sibling frame %p\n", kidFrame);
// is a "special" frame
// We also need to search if the child content is anonymous and scoped
// to the parent content.
nsCOMPtr<nsIContent> parentScope;
kidContent->GetBindingParent(getter_AddRefs(parentScope));
if (parentContent == kidContent || IsFrameSpecial(kidFrame) ||
(parentContent && (parentContent == parentScope)))
{
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, parentContent.get());
#endif
nsIFrame* matchingFrame = FindFrameWithContent(aPresContext, kidFrame, parentContent,
aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
}
} }
#endif
} }
// Get the next sibling frame if (aHint) {
kidFrame->GetNextSibling(&kidFrame); // If we get here, and we had a hint, then we didn't find a
#ifdef NOISY_FINDFRAME // frame. The hint may have been a floated or absolutely
FFWC_doSibling++; // positioned frame, in which case we'd be off in the weeds
if (kidFrame) { // looking through something other than primary frame
printf(" searching sibling frame %p\n", kidFrame); // list. Reboot the search from scratch, without the hint, but
// using the null child list again.
aHint = nsnull;
} else {
NS_IF_RELEASE(listName);
aParentFrame->GetAdditionalChildListName(listIndex++, &listName);
} }
#endif } while(listName);
}
if (firstTime) { // We didn't find a matching frame. If aFrame has a next-in-flow,
firstTime = PR_FALSE; // then continue looking there
aParentFrame = GetNifOrSpecialSibling(aFrameManager, aParentFrame);
// If we get here, and we had a hint, then we didn't find a
// frame. The hint may have been a floated or absolutely
// positioned frame, in which case we'd be off in the weeds
// looking through something other than primary frame
// list. Reboot the search from scratch.
if (aHint)
goto keepLooking;
}
NS_IF_RELEASE(listName);
aParentFrame->GetAdditionalChildListName(listIndex++, &listName);
} while(listName);
// We didn't find a matching frame. If aFrame has a next-in-flow,
// then continue looking there
aParentFrame->GetNextInFlow(&aParentFrame);
if (aParentFrame) {
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
FFWC_nextInFlows++; if (aParentFrame) {
printf(" searching NIF frame %p\n", aParentFrame); FFWC_nextInFlows++;
printf(" searching NIF frame %p\n", aParentFrame);
}
#endif #endif
goto keepLooking; } while (aParentFrame);
}
// No matching frame // No matching frame
return nsnull; return nsnull;
@ -11978,7 +11973,8 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
aFrameManager->GetPrimaryFrameFor(parentContent, &parentFrame); aFrameManager->GetPrimaryFrameFor(parentContent, &parentFrame);
while (parentFrame) { while (parentFrame) {
// Search the child frames for a match // Search the child frames for a match
*aFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent, aHint); *aFrame = FindFrameWithContent(aPresContext, aFrameManager, parentFrame,
parentContent.get(), aContent, aHint);
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf("FindFrameWithContent returned %p\n", *aFrame); printf("FindFrameWithContent returned %p\n", *aFrame);
#endif #endif
@ -11993,7 +11989,9 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf("VERIFYING...\n"); printf("VERIFYING...\n");
#endif #endif
nsIFrame *verifyTestFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent, nsnull); nsIFrame *verifyTestFrame =
FindFrameWithContent(aPresContext, aFrameManager, parentFrame,
parentContent.get(), aContent, nsnull);
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf("VERIFY returned %p\n", verifyTestFrame); printf("VERIFY returned %p\n", verifyTestFrame);
#endif #endif
@ -14334,7 +14332,8 @@ nsCSSFrameConstructor::ReframeContainingBlock(nsIPresContext* aPresContext, nsIF
#ifdef DEBUG #ifdef DEBUG
if (gNoisyContentUpdates) { if (gNoisyContentUpdates) {
printf(" ==> blockContent=%p, parentContainer=%p\n", printf(" ==> blockContent=%p, parentContainer=%p\n",
blockContent.get(), parentContainer.get()); NS_STATIC_CAST(void*, blockContent),
NS_STATIC_CAST(void*, parentContainer));
} }
#endif #endif
PRInt32 ix; PRInt32 ix;

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

@ -901,6 +901,7 @@ protected:
* @param aHint an optional hint used to make the search for aFrame faster * @param aHint an optional hint used to make the search for aFrame faster
*/ */
nsIFrame* FindFrameWithContent(nsIPresContext* aPresContext, nsIFrame* FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIFrame* aParentFrame, nsIFrame* aParentFrame,
nsIContent* aParentContent, nsIContent* aParentContent,
nsIContent* aContent, nsIContent* aContent,

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

@ -3204,15 +3204,6 @@ nsCSSFrameConstructor::ConstructDocElementTableFrame(nsIPresShell* aPresS
return NS_OK; return NS_OK;
} }
static PRBool
IsCanvasFrame(nsIFrame* aFrame)
{
nsCOMPtr<nsIAtom> parentType;
aFrame->GetFrameType(getter_AddRefs(parentType));
return parentType.get() == nsLayoutAtoms::canvasFrame;
}
/** /**
* New one * New one
*/ */
@ -11748,14 +11739,30 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsIPresShell* aPresShell,
return rv; return rv;
} }
// Get the frame's next-in-flow, or, if it doesn't have one,
// its special sibling.
static nsIFrame*
GetNifOrSpecialSibling(nsIFrameManager *aFrameManager, nsIFrame *aFrame)
{
nsIFrame *result;
aFrame->GetNextInFlow(&result);
if (result)
return result;
if (IsFrameSpecial(aFrame))
GetSpecialSibling(aFrameManager, aFrame, &result);
return result;
}
// Helper function that searches the immediate child frames // Helper function that searches the immediate child frames
// (and their children if the frames are "special") // (and their children if the frames are "special")
// for a frame that maps the specified content object // for a frame that maps the specified content object
nsIFrame* nsIFrame*
nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext, nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame, nsIFrameManager* aFrameManager,
nsIContent* aParentContent, nsIFrame* aParentFrame,
nsIContent* aContent, nsIContent* aParentContent,
nsIContent* aContent,
nsFindFrameHint* aHint) nsFindFrameHint* aHint)
{ {
@ -11765,29 +11772,20 @@ nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext,
aContent, aParentFrame, aParentContent, aHint ? "set" : "NULL"); aContent, aParentFrame, aParentContent, aHint ? "set" : "NULL");
#endif #endif
NS_PRECONDITION(aParentFrame, "No frame to search!"); NS_ENSURE_TRUE(aParentFrame != nsnull, nsnull);
if (!aParentFrame) {
return nsnull;
}
nsCOMPtr<nsIContent> parentContent = aParentContent; // because we might change this when using the hint
PRBool firstTime = PR_TRUE; // marker to let us know to only use aHint the very first time through
// must be declared outside loop and above goto label "keepLooking"
keepLooking:
// Search for the frame in each child list that aParentFrame supports
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
do { do {
// Search for the frame in each child list that aParentFrame supports
nsIAtom* listName = nsnull;
PRInt32 listIndex = 0;
do {
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
FFWC_doLoop++; FFWC_doLoop++;
#endif #endif
nsIFrame* kidFrame=nsnull; nsIFrame* kidFrame=nsnull;
if (aHint && firstTime) // if we were given an hint, try to use it here to find a good
{ // if we were given an hint, try to use it here, unless the parent frame is special // previous frame to start our search (|kidFrame|).
if (!IsFrameSpecial(aParentFrame)) if (aHint) {
{
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling); printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling);
#endif #endif
@ -11800,141 +11798,138 @@ keepLooking:
nsIFrame *parentFrame=nsnull; nsIFrame *parentFrame=nsnull;
aHint->mPrimaryFrameForPrevSibling->GetParent(&parentFrame); aHint->mPrimaryFrameForPrevSibling->GetParent(&parentFrame);
if (parentFrame) { if (parentFrame) {
parentFrame->GetNextInFlow(&parentFrame); parentFrame = GetNifOrSpecialSibling(aFrameManager, parentFrame);
} }
if (parentFrame) if (parentFrame)
{ // if we found the next-in-flow for the parent of the hint frame, start with it's first child { // if we found the next-in-flow for the parent of the hint frame, start with it's first child
parentFrame->FirstChild(aPresContext, listName, &kidFrame); parentFrame->FirstChild(aPresContext, listName, &kidFrame);
if (kidFrame) // Leave |aParentFrame| as-is, since the only time we'll
{ // reuse it is if the hint fails.
aParentFrame = parentFrame; // if we found a match, make this the new starting point #ifdef DEBUG
aParentFrame->GetContent(getter_AddRefs(parentContent)); if (kidFrame) {
nsCOMPtr<nsIContent> parentContent;
parentFrame->GetContent(getter_AddRefs(parentContent));
NS_ASSERTION(parentContent == aParentContent,
"next-in-flow has different content");
} }
#endif
} }
} }
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf(" hint gives us kidFrame=%p with parent frame %p content %p\n", printf(" hint gives us kidFrame=%p with parent frame %p content %p\n",
kidFrame, aParentFrame, parentContent); kidFrame, aParentFrame, aParentContent);
#endif #endif
} }
} }
else if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning
{ aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
#ifdef NOISY_FINDFRAME
printf("skipping hint because parent frame is special\n");
#endif
} }
} while (kidFrame) {
if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning nsCOMPtr<nsIContent> kidContent;
aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
} // See if the child frame points to the content object we're
while (kidFrame) { // looking for
nsCOMPtr<nsIContent> kidContent; kidFrame->GetContent(getter_AddRefs(kidContent));
if (kidContent == aContent) {
// See if the child frame points to the content object we're nsCOMPtr<nsIAtom> frameType;
// looking for
kidFrame->GetContent(getter_AddRefs(kidContent));
if (kidContent.get() == aContent) {
nsCOMPtr<nsIAtom> frameType;
// We found a match. See if it's a placeholder frame // We found a match. See if it's a placeholder frame
kidFrame->GetFrameType(getter_AddRefs(frameType)); kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::placeholderFrame == frameType.get()) { if (nsLayoutAtoms::placeholderFrame == frameType.get()) {
// Ignore the placeholder and return the out-of-flow frame instead // Ignore the placeholder and return the out-of-flow frame instead
return ((nsPlaceholderFrame*)kidFrame)->GetOutOfFlowFrame(); return ((nsPlaceholderFrame*)kidFrame)->GetOutOfFlowFrame();
} else { } else {
// Check if kidframe is the :before pseudo frame for aContent. If it // Check if kidframe is the :before pseudo frame for aContent. If it
// is, and aContent is an element, then aContent might be a // is, and aContent is an element, then aContent might be a
// non-splittable-element, so the real primary frame could be the // non-splittable-element, so the real primary frame could be the
// next sibling. // next sibling.
if (aContent->IsContentOfType(nsIContent::eELEMENT) && if (aContent->IsContentOfType(nsIContent::eELEMENT) &&
IsGeneratedContentFor(aContent, kidFrame, nsCSSAtoms::beforePseudo)) { IsGeneratedContentFor(aContent, kidFrame, nsCSSAtoms::beforePseudo)) {
nsIFrame *nextSibling = nsnull; kidFrame->GetNextSibling(&kidFrame);
#ifdef DEBUG
NS_ASSERTION(kidFrame, ":before with no next sibling");
if (kidFrame) {
nsCOMPtr<nsIContent> nextSiblingContent;
kidFrame->GetContent(getter_AddRefs(nextSiblingContent));
kidFrame->GetNextSibling(&nextSibling); // Make sure the content matches, and because I'm paranoid,
if (nextSibling) { // make sure it's not the :after pseudo frame.
nsCOMPtr<nsIContent> nextSiblingContent;
nextSibling->GetContent(getter_AddRefs(nextSiblingContent));
// Make sure the content matches, and because I'm paranoid, NS_ASSERTION(nextSiblingContent.get() == aContent &&
// make sure it's not the :after pseudo frame. !IsGeneratedContentFor(aContent, kidFrame,
nsCSSAtoms::afterPseudo),
":before frame not followed by primary frame");
}
#endif
}
if (nextSiblingContent.get() == aContent && // Return the matching child frame
!IsGeneratedContentFor(aContent, nextSibling, nsCSSAtoms::afterPseudo)) return kidFrame;
kidFrame = nextSibling; }
}
// 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.
nsCOMPtr<nsIContent> parentScope;
kidContent->GetBindingParent(getter_AddRefs(parentScope));
if (aParentContent == kidContent ||
(aParentContent && (aParentContent == parentScope)))
{
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, aParentContent.get());
#endif
nsIFrame* matchingFrame =
FindFrameWithContent(aPresContext, aFrameManager, kidFrame,
aParentContent, aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
} }
} }
// Return the matching child frame
return kidFrame;
} }
}
// only do this if there is content // Get the next sibling frame
if (kidContent) { kidFrame->GetNextSibling(&kidFrame);
// We search the immediate children only, but if the child frame has #ifdef NOISY_FINDFRAME
// the same content pointer as its parent then we need to search its FFWC_doSibling++;
// child frames, too. if (kidFrame) {
// We also need to search the child frame's children if the child frame printf(" searching sibling frame %p\n", kidFrame);
// is a "special" frame
// We also need to search if the child content is anonymous and scoped
// to the parent content.
nsCOMPtr<nsIContent> parentScope;
kidContent->GetBindingParent(getter_AddRefs(parentScope));
if (parentContent == kidContent || IsFrameSpecial(kidFrame) ||
(parentContent && (parentContent == parentScope)))
{
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, parentContent.get());
#endif
nsIFrame* matchingFrame = FindFrameWithContent(aPresContext, kidFrame, parentContent,
aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
}
} }
#endif
} }
// Get the next sibling frame if (aHint) {
kidFrame->GetNextSibling(&kidFrame); // If we get here, and we had a hint, then we didn't find a
#ifdef NOISY_FINDFRAME // frame. The hint may have been a floated or absolutely
FFWC_doSibling++; // positioned frame, in which case we'd be off in the weeds
if (kidFrame) { // looking through something other than primary frame
printf(" searching sibling frame %p\n", kidFrame); // list. Reboot the search from scratch, without the hint, but
// using the null child list again.
aHint = nsnull;
} else {
NS_IF_RELEASE(listName);
aParentFrame->GetAdditionalChildListName(listIndex++, &listName);
} }
#endif } while(listName);
}
if (firstTime) { // We didn't find a matching frame. If aFrame has a next-in-flow,
firstTime = PR_FALSE; // then continue looking there
aParentFrame = GetNifOrSpecialSibling(aFrameManager, aParentFrame);
// If we get here, and we had a hint, then we didn't find a
// frame. The hint may have been a floated or absolutely
// positioned frame, in which case we'd be off in the weeds
// looking through something other than primary frame
// list. Reboot the search from scratch.
if (aHint)
goto keepLooking;
}
NS_IF_RELEASE(listName);
aParentFrame->GetAdditionalChildListName(listIndex++, &listName);
} while(listName);
// We didn't find a matching frame. If aFrame has a next-in-flow,
// then continue looking there
aParentFrame->GetNextInFlow(&aParentFrame);
if (aParentFrame) {
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
FFWC_nextInFlows++; if (aParentFrame) {
printf(" searching NIF frame %p\n", aParentFrame); FFWC_nextInFlows++;
printf(" searching NIF frame %p\n", aParentFrame);
}
#endif #endif
goto keepLooking; } while (aParentFrame);
}
// No matching frame // No matching frame
return nsnull; return nsnull;
@ -11978,7 +11973,8 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
aFrameManager->GetPrimaryFrameFor(parentContent, &parentFrame); aFrameManager->GetPrimaryFrameFor(parentContent, &parentFrame);
while (parentFrame) { while (parentFrame) {
// Search the child frames for a match // Search the child frames for a match
*aFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent, aHint); *aFrame = FindFrameWithContent(aPresContext, aFrameManager, parentFrame,
parentContent.get(), aContent, aHint);
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf("FindFrameWithContent returned %p\n", *aFrame); printf("FindFrameWithContent returned %p\n", *aFrame);
#endif #endif
@ -11993,7 +11989,9 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf("VERIFYING...\n"); printf("VERIFYING...\n");
#endif #endif
nsIFrame *verifyTestFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent, nsnull); nsIFrame *verifyTestFrame =
FindFrameWithContent(aPresContext, aFrameManager, parentFrame,
parentContent.get(), aContent, nsnull);
#ifdef NOISY_FINDFRAME #ifdef NOISY_FINDFRAME
printf("VERIFY returned %p\n", verifyTestFrame); printf("VERIFY returned %p\n", verifyTestFrame);
#endif #endif
@ -14334,7 +14332,8 @@ nsCSSFrameConstructor::ReframeContainingBlock(nsIPresContext* aPresContext, nsIF
#ifdef DEBUG #ifdef DEBUG
if (gNoisyContentUpdates) { if (gNoisyContentUpdates) {
printf(" ==> blockContent=%p, parentContainer=%p\n", printf(" ==> blockContent=%p, parentContainer=%p\n",
blockContent.get(), parentContainer.get()); NS_STATIC_CAST(void*, blockContent),
NS_STATIC_CAST(void*, parentContainer));
} }
#endif #endif
PRInt32 ix; PRInt32 ix;

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

@ -901,6 +901,7 @@ protected:
* @param aHint an optional hint used to make the search for aFrame faster * @param aHint an optional hint used to make the search for aFrame faster
*/ */
nsIFrame* FindFrameWithContent(nsIPresContext* aPresContext, nsIFrame* FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIFrame* aParentFrame, nsIFrame* aParentFrame,
nsIContent* aParentContent, nsIContent* aParentContent,
nsIContent* aContent, nsIContent* aContent,