зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
a2dc0c286f
Коммит
015b68bde1
|
@ -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,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче