the problem was a factorial algorithm for finding primary frames.
fixed by added a hinting mechanism that takes advantage of existing
primary frame cache, greatly reducing the cost for the common case.
r=rods
sr=waterson
This commit is contained in:
buster%netscape.com 2001-01-16 22:10:04 +00:00
Родитель e2e4ac628f
Коммит 6a93e50850
15 изменённых файлов: 723 добавлений и 79 удалений

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

@ -243,7 +243,8 @@ public:
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame);
nsIFrame** aFrame,
nsFindFrameHint* aHint);
// APIs for registering objects that can supply additional
// rules during processing.
@ -1320,10 +1321,11 @@ NS_IMETHODIMP
StyleSetImpl::FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame)
nsIFrame** aFrame,
nsFindFrameHint* aHint)
{
return mFrameConstructor->FindPrimaryFrameFor(aPresContext, aFrameManager,
aContent, aFrame);
aContent, aFrame, aHint);
}
void StyleSetImpl::List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets)

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

@ -268,6 +268,14 @@ NS_NewResizerFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
static NS_DEFINE_IID(kIStyleFrameConstructionIID, NS_ISTYLE_FRAME_CONSTRUCTION_IID);
#ifdef NOISY_FINDFRAME
static PRInt32 FFWC_totalCount=0;
static PRInt32 FFWC_doLoop=0;
static PRInt32 FFWC_doSibling=0;
static PRInt32 FFWC_recursions=0;
static PRInt32 FFWC_nextInFlows=0;
static PRInt32 FFWC_slowSearchForText=0;
#endif
//----------------------------------------------------------------------
//
@ -809,6 +817,17 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(void)
mGfxScrollFrame(nsnull)
{
NS_INIT_REFCNT();
#ifdef NS_DEBUG
mVerifyFastFindFrame = PR_FALSE;
// Get the pref for verifying the new fast find frame with hint code.
// Note that this makes finding frames *slower* than it was before the fix.
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
prefs->GetBoolPref("nglayout.debug.verifyFastFindFrame", &mVerifyFastFindFrame);
}
#endif
}
nsCSSFrameConstructor::~nsCSSFrameConstructor(void)
@ -4058,7 +4077,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell,
nsIFrame * comboboxFrame;
rv = NS_NewComboboxControlFrame(aPresShell, &comboboxFrame, flags);
// Determine geometric parent for the combobox frame
// Determine geometric parent for the combobox frame
nsIFrame* geometricParent = aParentFrame;
if (aIsAbsolutelyPositioned) {
geometricParent = aState.mAbsoluteItems.containingBlock;
@ -8422,6 +8441,7 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
const nsStyleDisplay* display = (const nsStyleDisplay*)
styleContext->GetStyleData(eStyleStruct_Display);
// XXX: perf question: why do we build "state" here?
nsFrameConstructorState state(aPresContext, mFixedContainingBlock,
GetAbsoluteContainingBlock(aPresContext, innerFrame),
GetFloaterContainingBlock(aPresContext, innerFrame),
@ -10823,20 +10843,80 @@ nsIFrame*
nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent)
nsIContent* aContent,
nsFindFrameHint* aHint)
{
#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
NS_PRECONDITION(aParentFrame, "No frame to search!");
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 {
nsIFrame* kidFrame;
aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
#ifdef NOISY_FINDFRAME
FFWC_doLoop++;
#endif
nsIFrame* kidFrame=nsnull;
if (aHint && firstTime)
{ // if we were given an hint, try to use it here, unless the parent frame is special
if (!IsFrameSpecial(aParentFrame))
{
#ifdef NOISY_FINDFRAME
printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling);
#endif
kidFrame = aHint->mPrimaryFrameForPrevSibling; // start with the primary frame for aContent's previous sibling
if (kidFrame) { // if we have this
kidFrame->GetNextSibling(&kidFrame); // then use the next sibling frame as our starting point
if (!kidFrame)
{ // the hint frame had no next frame. try the next-in-flow fo the parent of the hint frame
// if there is one
nsIFrame *parentFrame=nsnull;
aHint->mPrimaryFrameForPrevSibling->GetParent(&parentFrame);
if (parentFrame) {
parentFrame->GetNextInFlow(&parentFrame);
}
if (parentFrame)
{ // 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);
if (kidFrame)
{
aParentFrame = parentFrame; // if we found a match, make this the new starting point
aParentFrame->GetContent(getter_AddRefs(parentContent));
}
}
}
#ifdef NOISY_FINDFRAME
printf(" hint gives us kidFrame=%p with parent frame %p content %p\n",
kidFrame, aParentFrame, parentContent);
#endif
}
}
else
{
#ifdef NOISY_FINDFRAME
printf("skipping hint because parent frame is special\n");
#endif
}
firstTime = PR_FALSE;
}
if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning
aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
}
while (kidFrame) {
nsCOMPtr<nsIContent> kidContent;
@ -10866,10 +10946,16 @@ keepLooking:
// to the parent content.
nsCOMPtr<nsIContent> parentScope;
kidContent->GetBindingParent(getter_AddRefs(parentScope));
if (kidContent.get() == aParentContent || IsFrameSpecial(kidFrame) ||
(aParentContent && (aParentContent == parentScope.get()))) {
nsIFrame* matchingFrame = FindFrameWithContent(aPresContext, kidFrame, aParentContent,
aContent);
if (kidContent.get() == parentContent || IsFrameSpecial(kidFrame) ||
(parentContent && (parentContent == parentScope.get())))
{
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, parentContent);
#endif
nsIFrame* matchingFrame = FindFrameWithContent(aPresContext, kidFrame, parentContent,
aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
@ -10878,6 +10964,12 @@ keepLooking:
// Get the next sibling frame
kidFrame->GetNextSibling(&kidFrame);
#ifdef NOISY_FINDFRAME
FFWC_doSibling++;
if (kidFrame) {
printf(" searching sibling frame %p\n", kidFrame);
}
#endif
}
NS_IF_RELEASE(listName);
@ -10888,6 +10980,10 @@ keepLooking:
// then continue looking there
aParentFrame->GetNextInFlow(&aParentFrame);
if (aParentFrame) {
#ifdef NOISY_FINDFRAME
FFWC_nextInFlows++;
printf(" searching NIF frame %p\n", aParentFrame);
#endif
goto keepLooking;
}
@ -10902,8 +10998,11 @@ NS_IMETHODIMP
nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame)
nsIFrame** aFrame,
nsFindFrameHint* aHint)
{
NS_ASSERTION(aPresContext && aFrameManager && aContent && aFrame, "bad arg");
*aFrame = nsnull; // initialize OUT parameter
// Get the pres shell
@ -10930,8 +11029,28 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
aFrameManager->GetPrimaryFrameFor(parentContent, &parentFrame);
while (parentFrame) {
// Search the child frames for a match
*aFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent);
*aFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent, aHint);
#ifdef NOISY_FINDFRAME
printf("FindFrameWithContent returned %p\n", *aFrame);
#endif
#ifdef NS_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 (mVerifyFastFindFrame && aHint)
{
#ifdef NOISY_FINDFRAME
printf("VERIFYING...\n");
#endif
nsIFrame *verifyTestFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), 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) {
@ -10953,6 +11072,28 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
}
}
if (aHint && !*aFrame)
{ // if we had a hint, and we didn't get a frame, see if we should try the slow way
nsCOMPtr<nsIAtom>tag;
aContent->GetTag(*getter_AddRefs(tag));
if (nsLayoutAtoms::textTagName == tag.get())
{
#ifdef NOISY_FINDFRAME
FFWC_slowSearchForText++;
#endif
// since we're passing in a null hint, we're guaranteed to only recurse once
return FindPrimaryFrameFor(aPresContext, aFrameManager, aContent, aFrame, nsnull);
}
}
#ifdef NOISY_FINDFRAME
printf("%10s %10s %10s %10s %10s \n",
"total", "doLoop", "doSibling", "recur", "nextIF", "slowSearch");
printf("%10d %10d %10d %10d %10d \n",
FFWC_totalCount, FFWC_doLoop, FFWC_doSibling, FFWC_recursions,
FFWC_nextInFlows, FFWC_slowSearchForText);
#endif
return NS_OK;
}

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

@ -133,7 +133,8 @@ public:
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame);
nsIFrame** aFrame,
nsFindFrameHint* aHint);
NS_IMETHOD CreateTreeWidgetContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
@ -817,13 +818,21 @@ protected:
nsresult RecreateEntireFrameTree(nsIPresContext* aPresContext);
// 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* FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent);
/** 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 aPresContext the presentation context
* @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(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent,
nsFindFrameHint* aHint);
//----------------------------------------
@ -945,6 +954,11 @@ protected:
PRBool mGotGfxPrefs;
PRBool mHasGfxScrollbars;
#ifdef NS_DEBUG
PRBool mVerifyFastFindFrame; // if true, run both the old and new find frame code
// to validate that both ways get the same answer
#endif
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
};

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

@ -505,26 +505,65 @@ FrameManager::GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG_POINTER(aContent);
if (!aResult) {
if (!aContent || !aResult) {
return NS_ERROR_NULL_POINTER;
}
*aResult = nsnull; // initialize out param
nsresult rv;
if (mPrimaryFrameMap) {
mPrimaryFrameMap->Search(aContent, 0, (void**)aResult);
if (!*aResult) {
// 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.
nsCOMPtr<nsIStyleSet> styleSet;
nsCOMPtr<nsIPresContext> presContext;
// Give the frame construction code the opportunity to return the
// frame that maps the content object
mPresShell->GetStyleSet(getter_AddRefs(styleSet));
NS_ASSERTION(styleSet, "bad style set");
mPresShell->GetPresContext(getter_AddRefs(presContext));
styleSet->FindPrimaryFrameFor(presContext, this, aContent, aResult);
NS_ASSERTION(presContext, "bad presContext");
if (!styleSet || !presContext) {
return NS_ERROR_NULL_POINTER;
}
// 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;
nsCOMPtr<nsIContent> prevSibling, parent;
rv = aContent->GetParent(*getter_AddRefs(parent));
if (NS_SUCCEEDED(rv) && parent)
{
PRInt32 index;
rv = parent->IndexOf(aContent, index);
if (NS_SUCCEEDED(rv) && index>0) // no use looking if it's the first child
{
rv = parent->ChildAt(index-1, *getter_AddRefs(prevSibling));
if (NS_SUCCEEDED(rv) && prevSibling)
{
mPrimaryFrameMap->Search(prevSibling.get(), 0, (void**)&hint.mPrimaryFrameForPrevSibling);
}
}
}
// walk the frame tree to find the frame that maps aContent.
// Use the hint if we have it.
styleSet->FindPrimaryFrameFor(presContext, this, aContent, aResult,
hint.mPrimaryFrameForPrevSibling ? &hint : nsnull);
}
} else {
*aResult = nsnull;
}
return NS_OK;
}
@ -533,6 +572,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
nsIFrame* aPrimaryFrame)
{
NS_ENSURE_ARG_POINTER(aContent);
// it's ok if aPrimaryFrame is null
// If aPrimaryFrame is NULL, then remove the mapping
if (!aPrimaryFrame) {
@ -551,6 +591,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
// Add a mapping to the hash table
mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame, nsnull);
}
return NS_OK;
}

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

@ -796,8 +796,9 @@ public:
* The first frame that maps that content is asked to deal with the
* change by generating an incremental reflow command.
*
* @param aIndexInParent the index in the content container where
* the new content was deleted.
* @param aPresContext the presentation context
* @param aContent the content node that was changed
* @param aSubContent a hint to the frame about the change
*/
NS_IMETHOD ContentChanged(nsIPresContext* aPresContext,
nsIContent* aChild,

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

@ -23,6 +23,7 @@
#define nsIStyleFrameConstruction_h___
#include "nsISupports.h"
#include "nsIStyleSet.h"
class nsIPresShell;
class nsIPresContext;
@ -39,89 +40,287 @@ class nsILayoutHistoryState;
#define NS_ISTYLE_FRAME_CONSTRUCTION_IID \
{0xa6cf9066, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
/** Interface for objects that handle frame construction based on style.
* All frame construction goes through an object that implements this interface.
* Frames are built based on the state of the content model and the style model.
* Changes to either content or style can cause changes to the frame model.
*/
class nsIStyleFrameConstruction : public nsISupports {
public:
/**
* Create frames for the root content element and its child content.
*/
* Create frames for the root content element and its child content.
*
* @param aPresShell the presentation shell for which we will consturct a root frame
* @param aPresContext the presentation context
* @param aDocElement the content node to map into a root frame
* @param aFrameSubTree [OUT] the resulting frame tree (a root frame and its children)
*
* @return NS_OK
*/
NS_IMETHOD ConstructRootFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsIContent* aDocElement,
nsIFrame*& aFrameSubTree) = 0;
// Causes reconstruction of a frame hierarchy rooted by the
// document element frame. This is often called when radical style
// change precludes incremental reflow.
/**
* Causes reconstruction of a frame hierarchy rooted by the
* document element frame. This is often called when radical style
* change precludes incremental reflow.
*
* @param aPresContext the presentation context
*
* @return NS_OK
*/
NS_IMETHOD ReconstructDocElementHierarchy(nsIPresContext* aPresContext) = 0;
/////////////// Content change notifications //////////////////
/**
* Notification that content was appended in the content tree.
* This may have the side effect of creating frames for the new content.
*
* @param aPresContext the presentation context
* @param aContainer the content node into which content was appended
* @param aNewIndexInContainer the index in aContainer at which the first
* content node was appended.
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD ContentAppended(nsIPresContext* aPresContext,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer) = 0;
/**
* Notification that content was inserted in the content tree.
* This may have the side effect of creating frames for the new content.
*
* @param aPresContext the presentation context
* @param aContainer the content node into which content was appended
* @param aChild the content node that was inserted
* @param aNewIndexInContainer the index of aChild in aContainer
* @param aFrameState the layout history object used to initialize the new frame(s)
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD ContentInserted(nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer,
nsILayoutHistoryState* aFrameState) = 0;
/**
* Notification that content was replaced in the content tree.
* This may have the side effect of creating frames for the new content.
*
* @param aPresContext the presentation context
* @param aContainer the content node into which content was appended
* @param aOldChild the content node that was replaced
* @param aNewChild the new content node that replaced aOldChild
* @param aNewIndexInContainer the index of aNewChild in aContainer
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD ContentReplaced(nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer) = 0;
/**
* Notification that content was inserted in the content tree.
* This may have the side effect of changing the frame tree
*
* @param aPresContext the presentation context
* @param aContainer the content node into which content was appended
* @param aChild the content node that was inserted
* @param aNewIndexInContainer the index of aChild in aContainer
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD ContentRemoved(nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
/**
* Notification that content was changed in the content tree.
* This may have the side effect of changing the frame tree
*
* @param aPresContext the presentation context
* @param aContent the content node that was changed
* @param aSubContent a hint to the frame system about the change
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD ContentChanged(nsIPresContext* aPresContext,
nsIContent* aContent,
nsISupports* aSubContent) = 0;
/**
* Notification that the state of a content node has changed.
* (ie: gained or lost focus, became active or hovered over)
*
* @param aPresContext the presentation context
* @param aContent1 the content node whose state was changed
* @param aContent2 an optional second content node whose state
* has also changed. The meaning of aContent2
* depends on the type of state change.
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD ContentStatesChanged(nsIPresContext* aPresContext,
nsIContent* aContent1,
nsIContent* aContent2) = 0;
/**
* Notification that an attribute was changed for a content node
* This may have the side effect of changing the frame tree
*
* @param aPresContext the presentation context
* @param aContent the content node on which an attribute was changed
* @param aNameSpaceID the name space for the changed attribute
* @param aAttribute the attribute that was changed
* @param aHint a hint about the effect of the change
* see nsStyleConsts.h for legal values
* any of the consts of the form NS_STYLE_HINT_*
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aHint) = 0;
// Style change notifications
/////////////// Style change notifications //////////////////
/**
* A StyleRule has just been modified within a style sheet.
*
* @param aDocument The document being observed
* @param aStyleSheet the StyleSheet that contians the rule
* @param aStyleRule the rule that was modified
* @param aHint some possible info about the nature of the change.
* see nsStyleConsts for hint values
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule,
PRInt32 aHint) = 0; // See nsStyleConsts fot hint values
/**
* A StyleRule has just been added to a style sheet.
* This method is called automatically when the rule gets
* added to the sheet. The style sheet passes this
* notification to the document. The notification is passed on
* to all of the document observers.
*
* @param aDocument The document being observed
* @param aStyleSheet the StyleSheet that has been modified
* @param aStyleRule the rule that was added
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) = 0;
/**
* A StyleRule has just been removed from a style sheet.
* This method is called automatically when the rule gets
* removed from the sheet. The style sheet passes this
* notification to the document. The notification is passed on
* to all of the document observers.
*
* @param aDocument The document being observed
* @param aStyleSheet the StyleSheet that has been modified
* @param aStyleRule the rule that was removed
*
* @return NS_OK
* @see nsIDocumentObserver
*/
NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) = 0;
/**
* Method that actually handles style changes for effected frames.
* Note: this may not need to be a public method. Use with extreme caution.
*
* @param aRestyleArray A list of effected frames.
* @param aPresContext The presentation context.
*
* @return NS_OK
*/
NS_IMETHOD ProcessRestyledFrames(nsStyleChangeList& aRestyleArray,
nsIPresContext* aPresContext) = 0;
// Notification that we were unable to render a replaced element.
NS_IMETHOD CantRenderReplacedElement(nsIPresShell* aPresShell,
/////////////// misc methods //////////////////////
/**
* Notification that we were unable to render a replaced element.
* Called when the replaced element can not be rendered, and we should
* instead render the element's contents.
* For HTML, the content object associated with aFrame should either be a IMG
* element or an OBJECT element.
* This may have the side effect of changing the frame tree.
*
* @param aPresShell the presentation shell
* @param aPresContext the presentation context
* @param aFrame the frame constructed for the replaced element
*
* @return NS_OK
*/
NS_IMETHOD CantRenderReplacedElement(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsIFrame* aFrame) = 0;
// Request to create a continuing frame
NS_IMETHOD CreateContinuingFrame(nsIPresShell* aPresShell,
/**
* Request to create a continuing frame
*
* @param aPresShell the presentation shell
* @param aPresContext the presentation context
* @param aFrame the frame for which we need a continuation
* @param aParentFrame the parent of aFrame
* @param aContinuingFrame [OUT] the resulting frame
*
* @return NS_OK
*/
NS_IMETHOD CreateContinuingFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIFrame* aParentFrame,
nsIFrame** aContinuingFrame) = 0;
// 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
/** 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
*
* @param aPresContext the presentation context
* @param aFrameManager the frame manager for the frame being sought
* @param aContent the content node for which we seek a frame
* @param aFrame [OUT] the resulting frame, if any. may be null,
* indicating that no frame maps aContent
* @param aHint an optional hint used to make the search for aFrame faster
*/
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame) = 0;
nsIFrame** aFrame,
nsFindFrameHint* aHint=nsnull) = 0;
};
#endif /* nsIStyleFrameConstruction_h___ */

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

@ -37,6 +37,7 @@ class nsIFrame;
class nsIDocument;
class nsIFrameManager;
class nsISupportsArray;
struct nsFindFrameHint;
#include "nsVoidArray.h"
class nsISizeOfHandler;
@ -192,13 +193,22 @@ public:
nsIFrame* aParentFrame,
nsIFrame** aContinuingFrame) = 0;
// 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
/** 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.
* @param aPresContext the pres context
* @param aFrameManager the frame manager
* @param aContent the content we need to find a frame for
* @param aFrame [OUT] the resulting frame
* @param aHint optional performance hint, may be null
*
* @return NS_OK. aFrame will be null if no frame could be found
*/
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame) = 0;
nsIFrame** aFrame,
nsFindFrameHint* aHint=0) = 0;
// APIs for registering objects that can supply additional
// rules during processing.
@ -296,5 +306,16 @@ protected:
nsUniqueStyleItems* ##_name = nsUniqueStyleItems::GetUniqueStyleItems(); \
NS_ASSERTION(##_name != nsnull, "UniqueItems cannot be null: error in nsUniqueStyleImtes factory");
/** a simple struct (that may someday be expanded)
* that contains data supplied by the caller to help
* the style set find a frame for a content node
*/
struct nsFindFrameHint
{
nsIFrame *mPrimaryFrameForPrevSibling; // weak ref to the primary frame for the content for which we need a frame
nsFindFrameHint() {
mPrimaryFrameForPrevSibling = nsnull;
};
};
#endif /* nsIStyleSet_h___ */

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

@ -537,6 +537,7 @@ nsFrameUtil::DumpTree(Node* aNode, FILE* aOutputFile, PRInt32 aIndent)
PRBool
nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
{
PRBool result = PR_TRUE;
for (;;) {
// Make sure both nodes are non-null, or at least agree with each other
if (nsnull == tree1) {
@ -563,6 +564,11 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
if (tree1->state != tree2->state) {
printf("frame state mismatch: 0x%x vs. 0x%x\n",
tree1->state, tree2->state);
printf("Node 1:\n");
DumpNode(tree1, stdout, 1);
printf("Node 2:\n");
DumpNode(tree2, stdout, 1);
//result = PR_FALSE; // we have a non-critical failure, so remember that but continue
}
if (tree1->bbox != tree2->bbox) {
printf("frame bbox mismatch: %d,%d,%d,%d vs. %d,%d,%d,%d\n",
@ -570,6 +576,11 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
tree1->bbox.width, tree1->bbox.height,
tree2->bbox.x, tree2->bbox.y,
tree2->bbox.width, tree2->bbox.height);
printf("Node 1:\n");
DumpNode(tree1, stdout, 1);
printf("Node 2:\n");
DumpNode(tree2, stdout, 1);
result = PR_FALSE; // we have a non-critical failure, so remember that but continue
}
if (tree1->styleData != tree2->styleData) {
printf("frame style data mismatch: %s vs. %s\n",
@ -606,6 +617,7 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
printf("child-list name mismatch: %s vs. %s\n",
list1->name ? list1->name : "(null)",
list2->name ? list2->name : "(null)");
result = PR_FALSE; // we have a non-critical failure, so remember that but continue
}
else {
PRBool equiv = CompareTrees(list1->node, list2->node);
@ -621,7 +633,7 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
tree1 = tree1->next;
tree2 = tree2->next;
}
return PR_TRUE;
return result;
}
NS_IMETHODIMP

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

@ -243,7 +243,8 @@ public:
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame);
nsIFrame** aFrame,
nsFindFrameHint* aHint);
// APIs for registering objects that can supply additional
// rules during processing.
@ -1320,10 +1321,11 @@ NS_IMETHODIMP
StyleSetImpl::FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame)
nsIFrame** aFrame,
nsFindFrameHint* aHint)
{
return mFrameConstructor->FindPrimaryFrameFor(aPresContext, aFrameManager,
aContent, aFrame);
aContent, aFrame, aHint);
}
void StyleSetImpl::List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets)

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

@ -537,6 +537,7 @@ nsFrameUtil::DumpTree(Node* aNode, FILE* aOutputFile, PRInt32 aIndent)
PRBool
nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
{
PRBool result = PR_TRUE;
for (;;) {
// Make sure both nodes are non-null, or at least agree with each other
if (nsnull == tree1) {
@ -563,6 +564,11 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
if (tree1->state != tree2->state) {
printf("frame state mismatch: 0x%x vs. 0x%x\n",
tree1->state, tree2->state);
printf("Node 1:\n");
DumpNode(tree1, stdout, 1);
printf("Node 2:\n");
DumpNode(tree2, stdout, 1);
//result = PR_FALSE; // we have a non-critical failure, so remember that but continue
}
if (tree1->bbox != tree2->bbox) {
printf("frame bbox mismatch: %d,%d,%d,%d vs. %d,%d,%d,%d\n",
@ -570,6 +576,11 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
tree1->bbox.width, tree1->bbox.height,
tree2->bbox.x, tree2->bbox.y,
tree2->bbox.width, tree2->bbox.height);
printf("Node 1:\n");
DumpNode(tree1, stdout, 1);
printf("Node 2:\n");
DumpNode(tree2, stdout, 1);
result = PR_FALSE; // we have a non-critical failure, so remember that but continue
}
if (tree1->styleData != tree2->styleData) {
printf("frame style data mismatch: %s vs. %s\n",
@ -606,6 +617,7 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
printf("child-list name mismatch: %s vs. %s\n",
list1->name ? list1->name : "(null)",
list2->name ? list2->name : "(null)");
result = PR_FALSE; // we have a non-critical failure, so remember that but continue
}
else {
PRBool equiv = CompareTrees(list1->node, list2->node);
@ -621,7 +633,7 @@ nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
tree1 = tree1->next;
tree2 = tree2->next;
}
return PR_TRUE;
return result;
}
NS_IMETHODIMP

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

@ -796,8 +796,9 @@ public:
* The first frame that maps that content is asked to deal with the
* change by generating an incremental reflow command.
*
* @param aIndexInParent the index in the content container where
* the new content was deleted.
* @param aPresContext the presentation context
* @param aContent the content node that was changed
* @param aSubContent a hint to the frame about the change
*/
NS_IMETHOD ContentChanged(nsIPresContext* aPresContext,
nsIContent* aChild,

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

@ -505,26 +505,65 @@ FrameManager::GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG_POINTER(aContent);
if (!aResult) {
if (!aContent || !aResult) {
return NS_ERROR_NULL_POINTER;
}
*aResult = nsnull; // initialize out param
nsresult rv;
if (mPrimaryFrameMap) {
mPrimaryFrameMap->Search(aContent, 0, (void**)aResult);
if (!*aResult) {
// 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.
nsCOMPtr<nsIStyleSet> styleSet;
nsCOMPtr<nsIPresContext> presContext;
// Give the frame construction code the opportunity to return the
// frame that maps the content object
mPresShell->GetStyleSet(getter_AddRefs(styleSet));
NS_ASSERTION(styleSet, "bad style set");
mPresShell->GetPresContext(getter_AddRefs(presContext));
styleSet->FindPrimaryFrameFor(presContext, this, aContent, aResult);
NS_ASSERTION(presContext, "bad presContext");
if (!styleSet || !presContext) {
return NS_ERROR_NULL_POINTER;
}
// 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;
nsCOMPtr<nsIContent> prevSibling, parent;
rv = aContent->GetParent(*getter_AddRefs(parent));
if (NS_SUCCEEDED(rv) && parent)
{
PRInt32 index;
rv = parent->IndexOf(aContent, index);
if (NS_SUCCEEDED(rv) && index>0) // no use looking if it's the first child
{
rv = parent->ChildAt(index-1, *getter_AddRefs(prevSibling));
if (NS_SUCCEEDED(rv) && prevSibling)
{
mPrimaryFrameMap->Search(prevSibling.get(), 0, (void**)&hint.mPrimaryFrameForPrevSibling);
}
}
}
// walk the frame tree to find the frame that maps aContent.
// Use the hint if we have it.
styleSet->FindPrimaryFrameFor(presContext, this, aContent, aResult,
hint.mPrimaryFrameForPrevSibling ? &hint : nsnull);
}
} else {
*aResult = nsnull;
}
return NS_OK;
}
@ -533,6 +572,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
nsIFrame* aPrimaryFrame)
{
NS_ENSURE_ARG_POINTER(aContent);
// it's ok if aPrimaryFrame is null
// If aPrimaryFrame is NULL, then remove the mapping
if (!aPrimaryFrame) {
@ -551,6 +591,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
// Add a mapping to the hash table
mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame, nsnull);
}
return NS_OK;
}

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

@ -268,6 +268,14 @@ NS_NewResizerFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
static NS_DEFINE_IID(kIStyleFrameConstructionIID, NS_ISTYLE_FRAME_CONSTRUCTION_IID);
#ifdef NOISY_FINDFRAME
static PRInt32 FFWC_totalCount=0;
static PRInt32 FFWC_doLoop=0;
static PRInt32 FFWC_doSibling=0;
static PRInt32 FFWC_recursions=0;
static PRInt32 FFWC_nextInFlows=0;
static PRInt32 FFWC_slowSearchForText=0;
#endif
//----------------------------------------------------------------------
//
@ -809,6 +817,17 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(void)
mGfxScrollFrame(nsnull)
{
NS_INIT_REFCNT();
#ifdef NS_DEBUG
mVerifyFastFindFrame = PR_FALSE;
// Get the pref for verifying the new fast find frame with hint code.
// Note that this makes finding frames *slower* than it was before the fix.
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
prefs->GetBoolPref("nglayout.debug.verifyFastFindFrame", &mVerifyFastFindFrame);
}
#endif
}
nsCSSFrameConstructor::~nsCSSFrameConstructor(void)
@ -4058,7 +4077,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell,
nsIFrame * comboboxFrame;
rv = NS_NewComboboxControlFrame(aPresShell, &comboboxFrame, flags);
// Determine geometric parent for the combobox frame
// Determine geometric parent for the combobox frame
nsIFrame* geometricParent = aParentFrame;
if (aIsAbsolutelyPositioned) {
geometricParent = aState.mAbsoluteItems.containingBlock;
@ -8422,6 +8441,7 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
const nsStyleDisplay* display = (const nsStyleDisplay*)
styleContext->GetStyleData(eStyleStruct_Display);
// XXX: perf question: why do we build "state" here?
nsFrameConstructorState state(aPresContext, mFixedContainingBlock,
GetAbsoluteContainingBlock(aPresContext, innerFrame),
GetFloaterContainingBlock(aPresContext, innerFrame),
@ -10823,20 +10843,80 @@ nsIFrame*
nsCSSFrameConstructor::FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent)
nsIContent* aContent,
nsFindFrameHint* aHint)
{
#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
NS_PRECONDITION(aParentFrame, "No frame to search!");
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 {
nsIFrame* kidFrame;
aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
#ifdef NOISY_FINDFRAME
FFWC_doLoop++;
#endif
nsIFrame* kidFrame=nsnull;
if (aHint && firstTime)
{ // if we were given an hint, try to use it here, unless the parent frame is special
if (!IsFrameSpecial(aParentFrame))
{
#ifdef NOISY_FINDFRAME
printf(" hint frame is %p\n", aHint->mPrimaryFrameForPrevSibling);
#endif
kidFrame = aHint->mPrimaryFrameForPrevSibling; // start with the primary frame for aContent's previous sibling
if (kidFrame) { // if we have this
kidFrame->GetNextSibling(&kidFrame); // then use the next sibling frame as our starting point
if (!kidFrame)
{ // the hint frame had no next frame. try the next-in-flow fo the parent of the hint frame
// if there is one
nsIFrame *parentFrame=nsnull;
aHint->mPrimaryFrameForPrevSibling->GetParent(&parentFrame);
if (parentFrame) {
parentFrame->GetNextInFlow(&parentFrame);
}
if (parentFrame)
{ // 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);
if (kidFrame)
{
aParentFrame = parentFrame; // if we found a match, make this the new starting point
aParentFrame->GetContent(getter_AddRefs(parentContent));
}
}
}
#ifdef NOISY_FINDFRAME
printf(" hint gives us kidFrame=%p with parent frame %p content %p\n",
kidFrame, aParentFrame, parentContent);
#endif
}
}
else
{
#ifdef NOISY_FINDFRAME
printf("skipping hint because parent frame is special\n");
#endif
}
firstTime = PR_FALSE;
}
if (!kidFrame) { // we didn't have enough info to prune, start searching from the beginning
aParentFrame->FirstChild(aPresContext, listName, &kidFrame);
}
while (kidFrame) {
nsCOMPtr<nsIContent> kidContent;
@ -10866,10 +10946,16 @@ keepLooking:
// to the parent content.
nsCOMPtr<nsIContent> parentScope;
kidContent->GetBindingParent(getter_AddRefs(parentScope));
if (kidContent.get() == aParentContent || IsFrameSpecial(kidFrame) ||
(aParentContent && (aParentContent == parentScope.get()))) {
nsIFrame* matchingFrame = FindFrameWithContent(aPresContext, kidFrame, aParentContent,
aContent);
if (kidContent.get() == parentContent || IsFrameSpecial(kidFrame) ||
(parentContent && (parentContent == parentScope.get())))
{
#ifdef NOISY_FINDFRAME
FFWC_recursions++;
printf(" recursing with new parent set to kidframe=%p, parentContent=%p\n",
kidFrame, parentContent);
#endif
nsIFrame* matchingFrame = FindFrameWithContent(aPresContext, kidFrame, parentContent,
aContent, nsnull);
if (matchingFrame) {
return matchingFrame;
@ -10878,6 +10964,12 @@ keepLooking:
// Get the next sibling frame
kidFrame->GetNextSibling(&kidFrame);
#ifdef NOISY_FINDFRAME
FFWC_doSibling++;
if (kidFrame) {
printf(" searching sibling frame %p\n", kidFrame);
}
#endif
}
NS_IF_RELEASE(listName);
@ -10888,6 +10980,10 @@ keepLooking:
// then continue looking there
aParentFrame->GetNextInFlow(&aParentFrame);
if (aParentFrame) {
#ifdef NOISY_FINDFRAME
FFWC_nextInFlows++;
printf(" searching NIF frame %p\n", aParentFrame);
#endif
goto keepLooking;
}
@ -10902,8 +10998,11 @@ NS_IMETHODIMP
nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame)
nsIFrame** aFrame,
nsFindFrameHint* aHint)
{
NS_ASSERTION(aPresContext && aFrameManager && aContent && aFrame, "bad arg");
*aFrame = nsnull; // initialize OUT parameter
// Get the pres shell
@ -10930,8 +11029,28 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
aFrameManager->GetPrimaryFrameFor(parentContent, &parentFrame);
while (parentFrame) {
// Search the child frames for a match
*aFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent);
*aFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), aContent, aHint);
#ifdef NOISY_FINDFRAME
printf("FindFrameWithContent returned %p\n", *aFrame);
#endif
#ifdef NS_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 (mVerifyFastFindFrame && aHint)
{
#ifdef NOISY_FINDFRAME
printf("VERIFYING...\n");
#endif
nsIFrame *verifyTestFrame = FindFrameWithContent(aPresContext, parentFrame, parentContent.get(), 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) {
@ -10953,6 +11072,28 @@ nsCSSFrameConstructor::FindPrimaryFrameFor(nsIPresContext* aPresContext,
}
}
if (aHint && !*aFrame)
{ // if we had a hint, and we didn't get a frame, see if we should try the slow way
nsCOMPtr<nsIAtom>tag;
aContent->GetTag(*getter_AddRefs(tag));
if (nsLayoutAtoms::textTagName == tag.get())
{
#ifdef NOISY_FINDFRAME
FFWC_slowSearchForText++;
#endif
// since we're passing in a null hint, we're guaranteed to only recurse once
return FindPrimaryFrameFor(aPresContext, aFrameManager, aContent, aFrame, nsnull);
}
}
#ifdef NOISY_FINDFRAME
printf("%10s %10s %10s %10s %10s \n",
"total", "doLoop", "doSibling", "recur", "nextIF", "slowSearch");
printf("%10d %10d %10d %10d %10d \n",
FFWC_totalCount, FFWC_doLoop, FFWC_doSibling, FFWC_recursions,
FFWC_nextInFlows, FFWC_slowSearchForText);
#endif
return NS_OK;
}

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

@ -133,7 +133,8 @@ public:
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame);
nsIFrame** aFrame,
nsFindFrameHint* aHint);
NS_IMETHOD CreateTreeWidgetContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
@ -817,13 +818,21 @@ protected:
nsresult RecreateEntireFrameTree(nsIPresContext* aPresContext);
// 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* FindFrameWithContent(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent);
/** 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 aPresContext the presentation context
* @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(nsIPresContext* aPresContext,
nsIFrame* aParentFrame,
nsIContent* aParentContent,
nsIContent* aContent,
nsFindFrameHint* aHint);
//----------------------------------------
@ -945,6 +954,11 @@ protected:
PRBool mGotGfxPrefs;
PRBool mHasGfxScrollbars;
#ifdef NS_DEBUG
PRBool mVerifyFastFindFrame; // if true, run both the old and new find frame code
// to validate that both ways get the same answer
#endif
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
};

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

@ -243,7 +243,8 @@ public:
NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame);
nsIFrame** aFrame,
nsFindFrameHint* aHint);
// APIs for registering objects that can supply additional
// rules during processing.
@ -1320,10 +1321,11 @@ NS_IMETHODIMP
StyleSetImpl::FindPrimaryFrameFor(nsIPresContext* aPresContext,
nsIFrameManager* aFrameManager,
nsIContent* aContent,
nsIFrame** aFrame)
nsIFrame** aFrame,
nsFindFrameHint* aHint)
{
return mFrameConstructor->FindPrimaryFrameFor(aPresContext, aFrameManager,
aContent, aFrame);
aContent, aFrame, aHint);
}
void StyleSetImpl::List(FILE* out, PRInt32 aIndent, nsISupportsArray* aSheets)