From 8d092fcca8ebb7f2daefa45b03c874ea2a32a806 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Sun, 5 Jan 2003 05:05:17 +0000 Subject: [PATCH] ReResolveStyleContext needs to deal with :before/:after pseudos correctly. Bug 126072, r=dbaron, sr=roc+moz. Also fixes bug 141259 (incorrect warnings about style tree integrity). git-svn-id: svn://10.0.0.236/trunk@135852 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsCSSFrameConstructor.cpp | 16 ++ mozilla/layout/base/nsFrameManager.cpp | 85 ++++++++- mozilla/layout/base/nsLayoutUtils.cpp | 175 ++++++++++++++++++ mozilla/layout/base/nsLayoutUtils.h | 77 ++++++++ mozilla/layout/base/nsPresShell.cpp | 118 ++---------- mozilla/layout/base/public/MANIFEST | 1 + mozilla/layout/base/public/Makefile.in | 1 + mozilla/layout/base/public/nsIFrame.h | 24 +++ mozilla/layout/base/public/nsLayoutUtils.h | 77 ++++++++ mozilla/layout/base/src/Makefile.in | 1 + mozilla/layout/base/src/nsLayoutUtils.cpp | 175 ++++++++++++++++++ mozilla/layout/generic/nsIFrame.h | 24 +++ .../layout/html/base/src/nsFrameManager.cpp | 85 ++++++++- mozilla/layout/html/base/src/nsPresShell.cpp | 118 ++---------- .../html/style/src/nsCSSFrameConstructor.cpp | 16 ++ mozilla/layout/macbuild/layout.xml | 30 +++ .../base/src/nsMathMLContainerFrame.cpp | 7 + .../layout/mathml/base/src/nsMathMLFrame.cpp | 7 + .../mathml/base/src/nsMathMLTokenFrame.cpp | 7 + .../mathml/base/src/nsMathMLmtableFrame.cpp | 7 + 20 files changed, 839 insertions(+), 212 deletions(-) create mode 100644 mozilla/layout/base/nsLayoutUtils.cpp create mode 100644 mozilla/layout/base/nsLayoutUtils.h create mode 100644 mozilla/layout/base/public/nsLayoutUtils.h create mode 100644 mozilla/layout/base/src/nsLayoutUtils.cpp diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 5d537f8060f..32e178ceeab 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -10336,6 +10336,22 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList, ApplyRenderingChangeToTree(aPresContext, frame, nsnull, hint); } } +#ifdef DEBUG + // reget from content since it may have been regenerated... + if (content) { + nsIFrame* frame; + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + shell->GetPrimaryFrameFor(content, &frame); + if (frame) { + nsCOMPtr frameManager; + shell->GetFrameManager(getter_AddRefs(frameManager)); + frameManager->DebugVerifyStyleTree(aPresContext, frame); + } + } else { + NS_WARNING("Unable to test style tree integrity -- no content node"); + } +#endif } aChangeList.Clear(); return NS_OK; diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index 0e4356f50b3..3f0448c9fba 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -45,6 +45,7 @@ #include "nsPlaceholderFrame.h" #include "nsLayoutAtoms.h" #include "nsCSSAnonBoxes.h" +#include "nsCSSPseudoElements.h" #include "nsHTMLAtoms.h" #ifdef NS_DEBUG #include "nsISupportsArray.h" @@ -75,6 +76,7 @@ #include "nsPrintfCString.h" #include "nsDummyLayoutRequest.h" #include "nsLayoutErrors.h" +#include "nsLayoutUtils.h" #ifdef DEBUG //#define NOISY_DEBUG @@ -1742,9 +1744,26 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, else if (pseudoTag) { nsIContent* pseudoContent = aParentContent ? aParentContent : localContent; - aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, + if (pseudoTag == nsCSSPseudoElements::before || + pseudoTag == nsCSSPseudoElements::after) { + // XXX what other pseudos do we need to treat like this? + aPresContext->ProbePseudoStyleContextFor(pseudoContent, pseudoTag, parentContext, &newContext); + if (!newContext) { + // This pseudo should no longer exist; gotta reframe + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, pseudoContent, + nsChangeHint_ReconstructFrame); + // We're reframing anyway; just keep the same context + newContext = oldContext; + NS_ADDREF(newContext); + } + } else { + aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, + parentContext, + &newContext); + } NS_RELEASE(pseudoTag); } else { @@ -1895,6 +1914,67 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, aResultChange = aMinChange; if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { + if (localContent && localContent->IsContentOfType(nsIContent::eELEMENT)) { + // Check for a new :before pseudo and an existing :before + // frame, but only if the frame is the first-in-flow. + nsIFrame* prevInFlow = nsnull; + aFrame->GetPrevInFlow(&prevInFlow); + if (!prevInFlow) { + // Checking for a :before frame is cheaper than getting the + // :before style context. + nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(aFrame, + aPresContext); + if (!beforeFrame) { + // Look for a new :before style context + nsCOMPtr newBeforeContext; + aPresContext->ProbePseudoStyleContextFor(localContent, + nsCSSPseudoElements::before, + newContext, + getter_AddRefs(newBeforeContext)); + if (newBeforeContext) { + // Have to create the new :before frame + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); + } + } + } + } + } + + + if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { + if (localContent && localContent->IsContentOfType(nsIContent::eELEMENT)) { + // Check for new :after content, but only if the frame is the first-in-flow. + nsIFrame* nextInFlow = nsnull; + aFrame->GetNextInFlow(&nextInFlow); + + if (!nextInFlow) { + // Getting the :after frame is + // more expensive than getting the pseudo context, so get the + // pseudo context first. + nsCOMPtr newAfterContext; + aPresContext->ProbePseudoStyleContextFor(localContent, + nsCSSPseudoElements::after, + newContext, + getter_AddRefs(newAfterContext)); + if (newAfterContext) { + // Check whether we already have an :after frame + nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aFrame, + aPresContext); + if (!afterFrame) { + // have to create one + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); + } + } + } + } + } + + if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { + // There is no need to waste time crawling into a frame's children on a frame change. // The act of reconstructing frames will force new style contexts to be resolved on all // of this frame's descendants anyway, so we want to avoid wasting time processing @@ -1993,9 +2073,6 @@ FrameManager::ComputeStyleChangeFor(nsIPresContext* aPresContext, ReResolveStyleContext(aPresContext, frame, nsnull, aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, frameChange); -#ifdef NS_DEBUG - VerifyStyleTree(aPresContext, frame, nsnull); -#endif NS_UpdateHint(aTopLevelChange, frameChange); if (aTopLevelChange & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame)) { diff --git a/mozilla/layout/base/nsLayoutUtils.cpp b/mozilla/layout/base/nsLayoutUtils.cpp new file mode 100644 index 00000000000..27bcdd55356 --- /dev/null +++ b/mozilla/layout/base/nsLayoutUtils.cpp @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsLayoutUtils.h" +#include "nsIFrame.h" +#include "nsIPresContext.h" +#include "nsIContent.h" +#include "nsFrameList.h" + +/** + * A namespace class for static layout utilities. + */ + +/** + * GetFirstChildFrame returns the first "real" child frame of a + * given frame. It will descend down into pseudo-frames (unless the + * pseudo-frame is the :before generated frame). + * @param aPresContext the prescontext + * @param aFrame the frame + * @param aFrame the frame's content node + */ +static nsIFrame* +GetFirstChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + nsIFrame* childFrame; + + // Get the first child frame + aFrame->FirstChild(aPresContext, nsnull, &childFrame); + + // If the child frame is a pseudo-frame, then return its first child. + // Note that the frame we create for the generated content is also a + // pseudo-frame and so don't drill down in that case + if (childFrame && + childFrame->IsPseudoFrame(aContent) && + !childFrame->IsGeneratedContentFrame()) { + return GetFirstChildFrame(aPresContext, childFrame, aContent); + } + + return childFrame; +} + +/** + * GetLastChildFrame returns the last "real" child frame of a + * given frame. It will descend down into pseudo-frames (unless the + * pseudo-frame is the :after generated frame). + * @param aPresContext the prescontext + * @param aFrame the frame + * @param aFrame the frame's content node + */ +static nsIFrame* +GetLastChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + // Get the last in flow frame + nsIFrame* lastInFlow; + do { + lastInFlow = aFrame; + lastInFlow->GetNextInFlow(&aFrame); + } while (aFrame); + + // Get the last child frame + nsIFrame* firstChildFrame; + lastInFlow->FirstChild(aPresContext, nsnull, &firstChildFrame); + if (firstChildFrame) { + nsFrameList frameList(firstChildFrame); + nsIFrame* lastChildFrame = frameList.LastChild(); + + NS_ASSERTION(lastChildFrame, "unexpected error"); + + // Get the frame's first-in-flow. This matters in case the frame has + // been continuted across multiple lines + while (PR_TRUE) { + nsIFrame* prevInFlow; + lastChildFrame->GetPrevInFlow(&prevInFlow); + if (prevInFlow) { + lastChildFrame = prevInFlow; + } else { + break; + } + } + + // If the last child frame is a pseudo-frame, then return its last child. + // Note that the frame we create for the generated content is also a + // pseudo-frame and so don't drill down in that case + if (lastChildFrame && + lastChildFrame->IsPseudoFrame(aContent) && + !lastChildFrame->IsGeneratedContentFrame()) { + return GetLastChildFrame(aPresContext, lastChildFrame, aContent); + } + + return lastChildFrame; + } + + return nsnull; +} + +// static +nsIFrame* +nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); +#ifdef DEBUG + nsIFrame* prevInFlow = nsnull; + aFrame->GetPrevInFlow(&prevInFlow); + NS_ASSERTION(!prevInFlow, "aFrame must be first-in-flow"); +#endif + + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + nsIFrame* firstFrame = GetFirstChildFrame(aPresContext, aFrame, content); + + if (firstFrame && firstFrame->IsGeneratedContentFrame()) { + return firstFrame; + } + + return nsnull; +} + +// static +nsIFrame* +nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + nsIFrame* lastFrame = GetLastChildFrame(aPresContext, aFrame, content); + + if (lastFrame && lastFrame->IsGeneratedContentFrame()) { + return lastFrame; + } + + return nsnull; +} diff --git a/mozilla/layout/base/nsLayoutUtils.h b/mozilla/layout/base/nsLayoutUtils.h new file mode 100644 index 00000000000..fed01d4d3a2 --- /dev/null +++ b/mozilla/layout/base/nsLayoutUtils.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla.org code. + * + * The Initial Developer of the Original Code is + * Boris Zbarsky . + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsLayoutUtils_h__ +#define nsLayoutUtils_h__ + +class nsIFrame; +class nsIPresContext; + +/** + * nsLayoutUtils is a namespace class used for various helper + * functions that are useful in multiple places in layout. The goal + * is not to define multiple copies of the same static helper. + */ +class nsLayoutUtils +{ +public: + /** + * GetBeforeFrame returns the :before frame of the given frame, if + * one exists. This is typically O(1). The frame passed in must be + * the first-in-flow. + * + * @param aFrame the frame whose :before is wanted + * @param aPresContext the prescontext + * @return the :before frame or nsnull if there isn't one + */ + static nsIFrame* GetBeforeFrame(nsIFrame* aFrame, nsIPresContext* aPresContext); + + /** + * GetAfterFrame returns the :after frame of the given frame, if one + * exists. This will walk the in-flow chain to the last-in-flow if + * needed. This function is typically O(N) in the number of child + * frames, following in-flows, etc. + * + * @param aFrame the frame whose :after is wanted + * @param aPresContext the prescontext + * @return the :after frame or nsnull if there isn't one + */ + static nsIFrame* GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext); + +}; + +#endif // nsLayoutUtils_h__ diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 541fb4b329e..ae3f2ba494b 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -108,6 +108,7 @@ #include "nsIDocShell.h" // for reflow observation #include "nsIDOMRange.h" #include "nsLayoutErrors.h" +#include "nsLayoutUtils.h" #ifdef MOZ_PERF_METRICS #include "nsITimeRecorder.h" #endif @@ -4569,94 +4570,6 @@ PresShell::SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState) return NS_OK; } -static PRBool -IsGeneratedContentFrame(nsIFrame* aFrame) -{ - nsFrameState frameState; - - aFrame->GetFrameState(&frameState); - return (frameState & NS_FRAME_GENERATED_CONTENT) != 0; -} - -static PRBool -IsPseudoFrame(nsIFrame* aFrame, nsIContent* aParentContent) -{ - nsCOMPtr content; - - aFrame->GetContent(getter_AddRefs(content)); - return content.get() == aParentContent; -} - -static nsIFrame* -GetFirstChildFrame(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent) -{ - nsIFrame* childFrame; - - // Get the first child frame - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - - // If the child frame is a pseudo-frame, then return its first child. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case - if (childFrame && IsPseudoFrame(childFrame, aContent) && - !IsGeneratedContentFrame(childFrame)) { - return GetFirstChildFrame(aPresContext, childFrame, aContent); - } - - return childFrame; -} - -static nsIFrame* -GetLastChildFrame(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent) -{ - NS_PRECONDITION(aFrame, "NULL frame pointer"); - - // Get the last in flow frame - nsIFrame* lastInFlow; - do { - lastInFlow = aFrame; - lastInFlow->GetNextInFlow(&aFrame); - } while (aFrame); - - // Get the last child frame - nsIFrame* firstChildFrame; - lastInFlow->FirstChild(aPresContext, nsnull, &firstChildFrame); - if (firstChildFrame) { - nsFrameList frameList(firstChildFrame); - nsIFrame* lastChildFrame = frameList.LastChild(); - - NS_ASSERTION(lastChildFrame, "unexpected error"); - - // Get the frame's first-in-flow. This matters in case the frame has - // been continuted across multiple lines - while (PR_TRUE) { - nsIFrame* prevInFlow; - lastChildFrame->GetPrevInFlow(&prevInFlow); - if (prevInFlow) { - lastChildFrame = prevInFlow; - } else { - break; - } - } - - // If the last child frame is a pseudo-frame, then return its last child. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case - if (lastChildFrame && IsPseudoFrame(lastChildFrame, aContent) && - !IsGeneratedContentFrame(lastChildFrame)) { - return GetLastChildFrame(aPresContext, lastChildFrame, aContent); - } - - return lastChildFrame; - } - - return nsnull; -} - NS_IMETHODIMP PresShell::GetGeneratedContentIterator(nsIContent* aContent, GeneratedContentType aType, @@ -4673,17 +4586,16 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent, if (primaryFrame) { // See whether it's a request for the before or after generated content if (Before == aType) { - // The most efficient thing to do is to get the first child frame, - // and see if it is associated with generated content - nsIFrame* firstChildFrame = GetFirstChildFrame(mPresContext, primaryFrame, aContent); - if (firstChildFrame && IsGeneratedContentFrame(firstChildFrame)) { + nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame, + mPresContext); + if (beforeFrame) { // Create an iterator - rv = NS_NewFrameContentIterator(mPresContext, firstChildFrame, aIterator); + rv = NS_NewFrameContentIterator(mPresContext, beforeFrame, aIterator); } } else { - // Avoid finding the last child frame unless we need to. Instead probe - // for the existence of the pseudo-element + // Avoid finding the :after frame unless we need to (it's + // expensive). Instead probe for the existence of the pseudo-element nsCOMPtr styleContext; nsCOMPtr pseudoStyleContext; @@ -4693,15 +4605,14 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent, styleContext, getter_AddRefs(pseudoStyleContext)); if (pseudoStyleContext) { - nsIFrame* lastChildFrame = GetLastChildFrame(mPresContext, primaryFrame, aContent); - if (lastChildFrame) - { // it is now legal for GetLastChildFrame to return null. see bug 52307 (a regression from bug 18754) - // in the case of a null child frame, we treat the frame as having no "after" style - // the "before" handler above already does this check - NS_ASSERTION(IsGeneratedContentFrame(lastChildFrame), + nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(primaryFrame, + mPresContext); + if (afterFrame) + { + NS_ASSERTION(afterFrame->IsGeneratedContentFrame(), "can't find generated content frame"); // Create an iterator - rv = NS_NewFrameContentIterator(mPresContext, lastChildFrame, aIterator); + rv = NS_NewFrameContentIterator(mPresContext, afterFrame, aIterator); } } } @@ -5490,6 +5401,9 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) if (aRebuildRuleTree) set->EndRuleTreeReconstruct(); + + VERIFY_STYLE_TREE; + return NS_OK; } diff --git a/mozilla/layout/base/public/MANIFEST b/mozilla/layout/base/public/MANIFEST index 452bc1ca9e7..07bae6ef9a1 100644 --- a/mozilla/layout/base/public/MANIFEST +++ b/mozilla/layout/base/public/MANIFEST @@ -41,6 +41,7 @@ nsIStyleFrameConstruction.h nsIStyleSet.h nsITextFrame.h nsLayoutErrors.h +nsLayoutUtils.h nsReflowType.h nsStyleChangeList.h nsStyleConsts.h diff --git a/mozilla/layout/base/public/Makefile.in b/mozilla/layout/base/public/Makefile.in index 884fec34375..e6053ee0817 100644 --- a/mozilla/layout/base/public/Makefile.in +++ b/mozilla/layout/base/public/Makefile.in @@ -68,6 +68,7 @@ nsIStyleContext.h \ nsIStyleFrameConstruction.h \ nsIStyleSet.h \ nsLayoutErrors.h \ +nsLayoutUtils.h \ nsReflowType.h \ nsStyleChangeList.h \ nsStyleConsts.h \ diff --git a/mozilla/layout/base/public/nsIFrame.h b/mozilla/layout/base/public/nsIFrame.h index b9de9beb248..b4d380b5b2d 100644 --- a/mozilla/layout/base/public/nsIFrame.h +++ b/mozilla/layout/base/public/nsIFrame.h @@ -1165,6 +1165,30 @@ public: PRBool aIsPre, PRBool* aResult) = 0; + /** + * IsGeneratedContentFrame returns whether a frame corresponds to + * generated content + * + * @return whether the frame correspods to generated content + */ + PRBool IsGeneratedContentFrame() { + return (mState & NS_FRAME_GENERATED_CONTENT) != 0; + } + + /** + * IsPseudoFrame returns whether a frame is a pseudo frame (eg an + * anonymous table-row frame created for a CSS table-cell without an + * enclosing table-row. + * + * @param aParentContent the content node corresponding to the parent frame + * @return whether the frame is a pseudo frame + */ + PRBool IsPseudoFrame(nsIContent* aParentContent) { + return mContent == aParentContent; + } + + + virtual void* GetProperty(nsIPresContext* aPresContext, nsIAtom* aPropertyName, PRBool aRemoveProperty) const = 0; diff --git a/mozilla/layout/base/public/nsLayoutUtils.h b/mozilla/layout/base/public/nsLayoutUtils.h new file mode 100644 index 00000000000..fed01d4d3a2 --- /dev/null +++ b/mozilla/layout/base/public/nsLayoutUtils.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla.org code. + * + * The Initial Developer of the Original Code is + * Boris Zbarsky . + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsLayoutUtils_h__ +#define nsLayoutUtils_h__ + +class nsIFrame; +class nsIPresContext; + +/** + * nsLayoutUtils is a namespace class used for various helper + * functions that are useful in multiple places in layout. The goal + * is not to define multiple copies of the same static helper. + */ +class nsLayoutUtils +{ +public: + /** + * GetBeforeFrame returns the :before frame of the given frame, if + * one exists. This is typically O(1). The frame passed in must be + * the first-in-flow. + * + * @param aFrame the frame whose :before is wanted + * @param aPresContext the prescontext + * @return the :before frame or nsnull if there isn't one + */ + static nsIFrame* GetBeforeFrame(nsIFrame* aFrame, nsIPresContext* aPresContext); + + /** + * GetAfterFrame returns the :after frame of the given frame, if one + * exists. This will walk the in-flow chain to the last-in-flow if + * needed. This function is typically O(N) in the number of child + * frames, following in-flows, etc. + * + * @param aFrame the frame whose :after is wanted + * @param aPresContext the prescontext + * @return the :after frame or nsnull if there isn't one + */ + static nsIFrame* GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext); + +}; + +#endif // nsLayoutUtils_h__ diff --git a/mozilla/layout/base/src/Makefile.in b/mozilla/layout/base/src/Makefile.in index 67664bde5ed..1c1c2aec50d 100644 --- a/mozilla/layout/base/src/Makefile.in +++ b/mozilla/layout/base/src/Makefile.in @@ -58,6 +58,7 @@ CPPSRCS = \ nsIntervalSet.cpp \ nsLayoutDebugger.cpp \ nsLayoutHistoryState.cpp \ + nsLayoutUtils.cpp \ nsPresContext.cpp \ nsPresState.cpp \ nsPrintContext.cpp \ diff --git a/mozilla/layout/base/src/nsLayoutUtils.cpp b/mozilla/layout/base/src/nsLayoutUtils.cpp new file mode 100644 index 00000000000..27bcdd55356 --- /dev/null +++ b/mozilla/layout/base/src/nsLayoutUtils.cpp @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsLayoutUtils.h" +#include "nsIFrame.h" +#include "nsIPresContext.h" +#include "nsIContent.h" +#include "nsFrameList.h" + +/** + * A namespace class for static layout utilities. + */ + +/** + * GetFirstChildFrame returns the first "real" child frame of a + * given frame. It will descend down into pseudo-frames (unless the + * pseudo-frame is the :before generated frame). + * @param aPresContext the prescontext + * @param aFrame the frame + * @param aFrame the frame's content node + */ +static nsIFrame* +GetFirstChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + nsIFrame* childFrame; + + // Get the first child frame + aFrame->FirstChild(aPresContext, nsnull, &childFrame); + + // If the child frame is a pseudo-frame, then return its first child. + // Note that the frame we create for the generated content is also a + // pseudo-frame and so don't drill down in that case + if (childFrame && + childFrame->IsPseudoFrame(aContent) && + !childFrame->IsGeneratedContentFrame()) { + return GetFirstChildFrame(aPresContext, childFrame, aContent); + } + + return childFrame; +} + +/** + * GetLastChildFrame returns the last "real" child frame of a + * given frame. It will descend down into pseudo-frames (unless the + * pseudo-frame is the :after generated frame). + * @param aPresContext the prescontext + * @param aFrame the frame + * @param aFrame the frame's content node + */ +static nsIFrame* +GetLastChildFrame(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIContent* aContent) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + // Get the last in flow frame + nsIFrame* lastInFlow; + do { + lastInFlow = aFrame; + lastInFlow->GetNextInFlow(&aFrame); + } while (aFrame); + + // Get the last child frame + nsIFrame* firstChildFrame; + lastInFlow->FirstChild(aPresContext, nsnull, &firstChildFrame); + if (firstChildFrame) { + nsFrameList frameList(firstChildFrame); + nsIFrame* lastChildFrame = frameList.LastChild(); + + NS_ASSERTION(lastChildFrame, "unexpected error"); + + // Get the frame's first-in-flow. This matters in case the frame has + // been continuted across multiple lines + while (PR_TRUE) { + nsIFrame* prevInFlow; + lastChildFrame->GetPrevInFlow(&prevInFlow); + if (prevInFlow) { + lastChildFrame = prevInFlow; + } else { + break; + } + } + + // If the last child frame is a pseudo-frame, then return its last child. + // Note that the frame we create for the generated content is also a + // pseudo-frame and so don't drill down in that case + if (lastChildFrame && + lastChildFrame->IsPseudoFrame(aContent) && + !lastChildFrame->IsGeneratedContentFrame()) { + return GetLastChildFrame(aPresContext, lastChildFrame, aContent); + } + + return lastChildFrame; + } + + return nsnull; +} + +// static +nsIFrame* +nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); +#ifdef DEBUG + nsIFrame* prevInFlow = nsnull; + aFrame->GetPrevInFlow(&prevInFlow); + NS_ASSERTION(!prevInFlow, "aFrame must be first-in-flow"); +#endif + + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + nsIFrame* firstFrame = GetFirstChildFrame(aPresContext, aFrame, content); + + if (firstFrame && firstFrame->IsGeneratedContentFrame()) { + return firstFrame; + } + + return nsnull; +} + +// static +nsIFrame* +nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame, nsIPresContext* aPresContext) +{ + NS_PRECONDITION(aFrame, "NULL frame pointer"); + + nsCOMPtr content; + aFrame->GetContent(getter_AddRefs(content)); + nsIFrame* lastFrame = GetLastChildFrame(aPresContext, aFrame, content); + + if (lastFrame && lastFrame->IsGeneratedContentFrame()) { + return lastFrame; + } + + return nsnull; +} diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index b9de9beb248..b4d380b5b2d 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -1165,6 +1165,30 @@ public: PRBool aIsPre, PRBool* aResult) = 0; + /** + * IsGeneratedContentFrame returns whether a frame corresponds to + * generated content + * + * @return whether the frame correspods to generated content + */ + PRBool IsGeneratedContentFrame() { + return (mState & NS_FRAME_GENERATED_CONTENT) != 0; + } + + /** + * IsPseudoFrame returns whether a frame is a pseudo frame (eg an + * anonymous table-row frame created for a CSS table-cell without an + * enclosing table-row. + * + * @param aParentContent the content node corresponding to the parent frame + * @return whether the frame is a pseudo frame + */ + PRBool IsPseudoFrame(nsIContent* aParentContent) { + return mContent == aParentContent; + } + + + virtual void* GetProperty(nsIPresContext* aPresContext, nsIAtom* aPropertyName, PRBool aRemoveProperty) const = 0; diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index 0e4356f50b3..3f0448c9fba 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -45,6 +45,7 @@ #include "nsPlaceholderFrame.h" #include "nsLayoutAtoms.h" #include "nsCSSAnonBoxes.h" +#include "nsCSSPseudoElements.h" #include "nsHTMLAtoms.h" #ifdef NS_DEBUG #include "nsISupportsArray.h" @@ -75,6 +76,7 @@ #include "nsPrintfCString.h" #include "nsDummyLayoutRequest.h" #include "nsLayoutErrors.h" +#include "nsLayoutUtils.h" #ifdef DEBUG //#define NOISY_DEBUG @@ -1742,9 +1744,26 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, else if (pseudoTag) { nsIContent* pseudoContent = aParentContent ? aParentContent : localContent; - aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, + if (pseudoTag == nsCSSPseudoElements::before || + pseudoTag == nsCSSPseudoElements::after) { + // XXX what other pseudos do we need to treat like this? + aPresContext->ProbePseudoStyleContextFor(pseudoContent, pseudoTag, parentContext, &newContext); + if (!newContext) { + // This pseudo should no longer exist; gotta reframe + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, pseudoContent, + nsChangeHint_ReconstructFrame); + // We're reframing anyway; just keep the same context + newContext = oldContext; + NS_ADDREF(newContext); + } + } else { + aPresContext->ResolvePseudoStyleContextFor(pseudoContent, pseudoTag, + parentContext, + &newContext); + } NS_RELEASE(pseudoTag); } else { @@ -1895,6 +1914,67 @@ FrameManager::ReResolveStyleContext(nsIPresContext* aPresContext, aResultChange = aMinChange; if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { + if (localContent && localContent->IsContentOfType(nsIContent::eELEMENT)) { + // Check for a new :before pseudo and an existing :before + // frame, but only if the frame is the first-in-flow. + nsIFrame* prevInFlow = nsnull; + aFrame->GetPrevInFlow(&prevInFlow); + if (!prevInFlow) { + // Checking for a :before frame is cheaper than getting the + // :before style context. + nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(aFrame, + aPresContext); + if (!beforeFrame) { + // Look for a new :before style context + nsCOMPtr newBeforeContext; + aPresContext->ProbePseudoStyleContextFor(localContent, + nsCSSPseudoElements::before, + newContext, + getter_AddRefs(newBeforeContext)); + if (newBeforeContext) { + // Have to create the new :before frame + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); + } + } + } + } + } + + + if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { + if (localContent && localContent->IsContentOfType(nsIContent::eELEMENT)) { + // Check for new :after content, but only if the frame is the first-in-flow. + nsIFrame* nextInFlow = nsnull; + aFrame->GetNextInFlow(&nextInFlow); + + if (!nextInFlow) { + // Getting the :after frame is + // more expensive than getting the pseudo context, so get the + // pseudo context first. + nsCOMPtr newAfterContext; + aPresContext->ProbePseudoStyleContextFor(localContent, + nsCSSPseudoElements::after, + newContext, + getter_AddRefs(newAfterContext)); + if (newAfterContext) { + // Check whether we already have an :after frame + nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aFrame, + aPresContext); + if (!afterFrame) { + // have to create one + NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame); + aChangeList.AppendChange(aFrame, content, + nsChangeHint_ReconstructFrame); + } + } + } + } + } + + if (!(aMinChange & (nsChangeHint_ReconstructFrame | nsChangeHint_ReconstructDoc))) { + // There is no need to waste time crawling into a frame's children on a frame change. // The act of reconstructing frames will force new style contexts to be resolved on all // of this frame's descendants anyway, so we want to avoid wasting time processing @@ -1993,9 +2073,6 @@ FrameManager::ComputeStyleChangeFor(nsIPresContext* aPresContext, ReResolveStyleContext(aPresContext, frame, nsnull, aAttrNameSpaceID, aAttribute, aChangeList, aMinChange, frameChange); -#ifdef NS_DEBUG - VerifyStyleTree(aPresContext, frame, nsnull); -#endif NS_UpdateHint(aTopLevelChange, frameChange); if (aTopLevelChange & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame)) { diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 541fb4b329e..ae3f2ba494b 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -108,6 +108,7 @@ #include "nsIDocShell.h" // for reflow observation #include "nsIDOMRange.h" #include "nsLayoutErrors.h" +#include "nsLayoutUtils.h" #ifdef MOZ_PERF_METRICS #include "nsITimeRecorder.h" #endif @@ -4569,94 +4570,6 @@ PresShell::SetHistoryState(nsILayoutHistoryState* aLayoutHistoryState) return NS_OK; } -static PRBool -IsGeneratedContentFrame(nsIFrame* aFrame) -{ - nsFrameState frameState; - - aFrame->GetFrameState(&frameState); - return (frameState & NS_FRAME_GENERATED_CONTENT) != 0; -} - -static PRBool -IsPseudoFrame(nsIFrame* aFrame, nsIContent* aParentContent) -{ - nsCOMPtr content; - - aFrame->GetContent(getter_AddRefs(content)); - return content.get() == aParentContent; -} - -static nsIFrame* -GetFirstChildFrame(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent) -{ - nsIFrame* childFrame; - - // Get the first child frame - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - - // If the child frame is a pseudo-frame, then return its first child. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case - if (childFrame && IsPseudoFrame(childFrame, aContent) && - !IsGeneratedContentFrame(childFrame)) { - return GetFirstChildFrame(aPresContext, childFrame, aContent); - } - - return childFrame; -} - -static nsIFrame* -GetLastChildFrame(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent) -{ - NS_PRECONDITION(aFrame, "NULL frame pointer"); - - // Get the last in flow frame - nsIFrame* lastInFlow; - do { - lastInFlow = aFrame; - lastInFlow->GetNextInFlow(&aFrame); - } while (aFrame); - - // Get the last child frame - nsIFrame* firstChildFrame; - lastInFlow->FirstChild(aPresContext, nsnull, &firstChildFrame); - if (firstChildFrame) { - nsFrameList frameList(firstChildFrame); - nsIFrame* lastChildFrame = frameList.LastChild(); - - NS_ASSERTION(lastChildFrame, "unexpected error"); - - // Get the frame's first-in-flow. This matters in case the frame has - // been continuted across multiple lines - while (PR_TRUE) { - nsIFrame* prevInFlow; - lastChildFrame->GetPrevInFlow(&prevInFlow); - if (prevInFlow) { - lastChildFrame = prevInFlow; - } else { - break; - } - } - - // If the last child frame is a pseudo-frame, then return its last child. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case - if (lastChildFrame && IsPseudoFrame(lastChildFrame, aContent) && - !IsGeneratedContentFrame(lastChildFrame)) { - return GetLastChildFrame(aPresContext, lastChildFrame, aContent); - } - - return lastChildFrame; - } - - return nsnull; -} - NS_IMETHODIMP PresShell::GetGeneratedContentIterator(nsIContent* aContent, GeneratedContentType aType, @@ -4673,17 +4586,16 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent, if (primaryFrame) { // See whether it's a request for the before or after generated content if (Before == aType) { - // The most efficient thing to do is to get the first child frame, - // and see if it is associated with generated content - nsIFrame* firstChildFrame = GetFirstChildFrame(mPresContext, primaryFrame, aContent); - if (firstChildFrame && IsGeneratedContentFrame(firstChildFrame)) { + nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame, + mPresContext); + if (beforeFrame) { // Create an iterator - rv = NS_NewFrameContentIterator(mPresContext, firstChildFrame, aIterator); + rv = NS_NewFrameContentIterator(mPresContext, beforeFrame, aIterator); } } else { - // Avoid finding the last child frame unless we need to. Instead probe - // for the existence of the pseudo-element + // Avoid finding the :after frame unless we need to (it's + // expensive). Instead probe for the existence of the pseudo-element nsCOMPtr styleContext; nsCOMPtr pseudoStyleContext; @@ -4693,15 +4605,14 @@ PresShell::GetGeneratedContentIterator(nsIContent* aContent, styleContext, getter_AddRefs(pseudoStyleContext)); if (pseudoStyleContext) { - nsIFrame* lastChildFrame = GetLastChildFrame(mPresContext, primaryFrame, aContent); - if (lastChildFrame) - { // it is now legal for GetLastChildFrame to return null. see bug 52307 (a regression from bug 18754) - // in the case of a null child frame, we treat the frame as having no "after" style - // the "before" handler above already does this check - NS_ASSERTION(IsGeneratedContentFrame(lastChildFrame), + nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(primaryFrame, + mPresContext); + if (afterFrame) + { + NS_ASSERTION(afterFrame->IsGeneratedContentFrame(), "can't find generated content frame"); // Create an iterator - rv = NS_NewFrameContentIterator(mPresContext, lastChildFrame, aIterator); + rv = NS_NewFrameContentIterator(mPresContext, afterFrame, aIterator); } } } @@ -5490,6 +5401,9 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree) if (aRebuildRuleTree) set->EndRuleTreeReconstruct(); + + VERIFY_STYLE_TREE; + return NS_OK; } diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 5d537f8060f..32e178ceeab 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -10336,6 +10336,22 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList, ApplyRenderingChangeToTree(aPresContext, frame, nsnull, hint); } } +#ifdef DEBUG + // reget from content since it may have been regenerated... + if (content) { + nsIFrame* frame; + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + shell->GetPrimaryFrameFor(content, &frame); + if (frame) { + nsCOMPtr frameManager; + shell->GetFrameManager(getter_AddRefs(frameManager)); + frameManager->DebugVerifyStyleTree(aPresContext, frame); + } + } else { + NS_WARNING("Unable to test style tree integrity -- no content node"); + } +#endif } aChangeList.Clear(); return NS_OK; diff --git a/mozilla/layout/macbuild/layout.xml b/mozilla/layout/macbuild/layout.xml index 9656e6db87c..8ec19461675 100644 --- a/mozilla/layout/macbuild/layout.xml +++ b/mozilla/layout/macbuild/layout.xml @@ -941,6 +941,13 @@ Text Debug + + Name + nsLayoutUtils.cpp + MacOS + Text + Debug + Name nsPresContext.cpp @@ -2137,6 +2144,11 @@ nsGalleyContext.cpp MacOS + + Name + nsLayoutUtils.cpp + MacOS + Name nsPresContext.cpp @@ -3852,6 +3864,13 @@ Text Debug + + Name + nsLayoutUtils.cpp + MacOS + Text + Debug + Name nsPresContext.cpp @@ -5068,6 +5087,11 @@ nsGalleyContext.cpp MacOS + + Name + nsLayoutUtils.cpp + MacOS + Name nsPresContext.cpp @@ -5932,6 +5956,12 @@ nsGalleyContext.cpp MacOS + + layout.shlb + Name + nsLayoutUtils.cpp + MacOS + layout.shlb Name diff --git a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp index 061ae9fd565..f25c1c9ce30 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -674,6 +674,13 @@ nsMathMLContainerFrame::PropagateScriptStyleFor(nsIPresContext* aPresContext, fm->ComputeStyleChangeFor(aPresContext, aFrame, kNameSpaceID_None, nsMathMLAtoms::fontsize, changeList, minChange, maxChange); +#ifdef DEBUG + // Use the parent frame to make sure we catch in-flows and such + nsIFrame* parentFrame; + aFrame->GetParent(&parentFrame); + fm->DebugVerifyStyleTree(aPresContext, + parentFrame ? parentFrame : aFrame); +#endif } } } diff --git a/mozilla/layout/mathml/base/src/nsMathMLFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLFrame.cpp index 6bfeb3b0dbd..1a20bc5522e 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLFrame.cpp @@ -717,6 +717,13 @@ nsMathMLFrame::MapAttributesIntoCSS(nsIPresContext* aPresContext, fm->ComputeStyleChangeFor(aPresContext, aFrame, kNameSpaceID_None, nsnull, changeList, minChange, maxChange); +#ifdef DEBUG + // Use the parent frame to make sure we catch in-flows and such + nsIFrame* parentFrame; + aFrame->GetParent(&parentFrame); + fm->DebugVerifyStyleTree(aPresContext, + parentFrame ? parentFrame : aFrame); +#endif } } diff --git a/mozilla/layout/mathml/base/src/nsMathMLTokenFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLTokenFrame.cpp index eb1d2250aa5..b8c0803e74a 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLTokenFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLTokenFrame.cpp @@ -358,6 +358,13 @@ nsMathMLTokenFrame::SetTextStyle(nsIPresContext* aPresContext) fm->ComputeStyleChangeFor(aPresContext, this, kNameSpaceID_None, nsMathMLAtoms::fontstyle, changeList, minChange, maxChange); +#ifdef DEBUG + // Use the parent frame to make sure we catch in-flows and such + nsIFrame* parentFrame; + GetParent(&parentFrame); + fm->DebugVerifyStyleTree(aPresContext, + parentFrame ? parentFrame : this); +#endif } } } diff --git a/mozilla/layout/mathml/base/src/nsMathMLmtableFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmtableFrame.cpp index 34012010653..8d5265fc723 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmtableFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmtableFrame.cpp @@ -299,6 +299,13 @@ MapAttributesInto(nsIPresContext* aPresContext, nsStyleChangeList changeList; fm->ComputeStyleChangeFor(aPresContext, aCellFrame, kNameSpaceID_None, nsnull, changeList, minChange, maxChange); +#ifdef DEBUG + // Use the parent frame to make sure we catch in-flows and such + nsIFrame* parentFrame; + aCellFrame->GetParent(&parentFrame); + fm->DebugVerifyStyleTree(aPresContext, + parentFrame ? parentFrame : aCellFrame); +#endif } } }