Bug 343445. Change inline reflow strategy to avoid looking ahead through words while measuring text. r+sr=dbaron
This commit is contained in:
@@ -249,6 +249,16 @@ nsTextFragment::AppendTo(nsAString& aString) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextFragment::AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const
|
||||||
|
{
|
||||||
|
if (mState.mIs2b) {
|
||||||
|
aString.Append(m2b + aOffset, aLength);
|
||||||
|
} else {
|
||||||
|
AppendASCIItoUTF16(Substring(m1b + aOffset, m1b + aOffset + aLength), aString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTextFragment::CopyTo(PRUnichar *aDest, PRInt32 aOffset, PRInt32 aCount)
|
nsTextFragment::CopyTo(PRUnichar *aDest, PRInt32 aOffset, PRInt32 aCount)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,6 +160,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void AppendTo(nsAString& aString) const;
|
void AppendTo(nsAString& aString) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a substring of the contents of this string fragment to aString.
|
||||||
|
* @param aOffset where to start the substring in this text fragment
|
||||||
|
* @param aLength the length of the substring
|
||||||
|
*/
|
||||||
|
void AppendTo(nsAString& aString, PRInt32 aOffset, PRInt32 aLength) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a copy of the fragments contents starting at offset for
|
* Make a copy of the fragments contents starting at offset for
|
||||||
* count characters. The offset and count will be adjusted to
|
* count characters. The offset and count will be adjusted to
|
||||||
|
|||||||
@@ -95,18 +95,11 @@ DestroyRectFunc(void* aFrame,
|
|||||||
delete NS_STATIC_CAST(nsRect*, aPropertyValue);
|
delete NS_STATIC_CAST(nsRect*, aPropertyValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsIFrame* GetParentOrPlaceholderFor(nsFrameManager* aFrameManager,
|
|
||||||
nsIFrame* aFrame) {
|
|
||||||
if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
|
|
||||||
return aFrameManager->GetPlaceholderFrameFor(aFrame);
|
|
||||||
}
|
|
||||||
return aFrame->GetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
|
static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
|
||||||
nsFrameManager* frameManager = aFrame->GetPresContext()->PresShell()->FrameManager();
|
nsFrameManager* frameManager = aFrame->GetPresContext()->PresShell()->FrameManager();
|
||||||
|
|
||||||
for (nsIFrame* f = aFrame; f; f = GetParentOrPlaceholderFor(frameManager, f)) {
|
for (nsIFrame* f = aFrame; f;
|
||||||
|
f = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, f)) {
|
||||||
if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
|
if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
|
||||||
return;
|
return;
|
||||||
f->AddStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
f->AddStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
||||||
@@ -135,7 +128,8 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
|
|||||||
|
|
||||||
nsFrameManager* frameManager = aFrame->GetPresContext()->PresShell()->FrameManager();
|
nsFrameManager* frameManager = aFrame->GetPresContext()->PresShell()->FrameManager();
|
||||||
|
|
||||||
for (nsIFrame* f = aFrame; f; f = GetParentOrPlaceholderFor(frameManager, f)) {
|
for (nsIFrame* f = aFrame; f;
|
||||||
|
f = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, f)) {
|
||||||
if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
|
if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
|
||||||
return;
|
return;
|
||||||
f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
#include "nsGUIEvent.h"
|
#include "nsGUIEvent.h"
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
#include "nsRegion.h"
|
#include "nsRegion.h"
|
||||||
|
#include "nsFrameManager.h"
|
||||||
|
|
||||||
#ifdef MOZ_SVG_FOREIGNOBJECT
|
#ifdef MOZ_SVG_FOREIGNOBJECT
|
||||||
#include "nsSVGForeignObjectFrame.h"
|
#include "nsSVGForeignObjectFrame.h"
|
||||||
@@ -995,3 +996,69 @@ nsLayoutUtils::GetFontMetricsForFrame(nsIFrame* aFrame,
|
|||||||
sc->GetStyleVisibility()->mLangGroup,
|
sc->GetStyleVisibility()->mLangGroup,
|
||||||
*aFontMetrics);
|
*aFontMetrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIFrame*
|
||||||
|
nsLayoutUtils::GetParentOrPlaceholderFor(nsFrameManager* aFrameManager,
|
||||||
|
nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
|
||||||
|
return aFrameManager->GetPlaceholderFrameFor(aFrame);
|
||||||
|
return aFrame->GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIFrame*
|
||||||
|
nsLayoutUtils::GetClosestCommonAncestorViaPlaceholders(nsIFrame* aFrame1,
|
||||||
|
nsIFrame* aFrame2,
|
||||||
|
nsIFrame* aKnownCommonAncestorHint)
|
||||||
|
{
|
||||||
|
NS_PRECONDITION(aFrame1, "aFrame1 must not be null");
|
||||||
|
NS_PRECONDITION(aFrame2, "aFrame2 must not be null");
|
||||||
|
|
||||||
|
nsPresContext* presContext = aFrame1->GetPresContext();
|
||||||
|
if (presContext != aFrame2->GetPresContext()) {
|
||||||
|
// different documents, no common ancestor
|
||||||
|
return nsnull;
|
||||||
|
}
|
||||||
|
nsFrameManager* frameManager = presContext->PresShell()->FrameManager();
|
||||||
|
|
||||||
|
nsAutoVoidArray frame1Ancestors;
|
||||||
|
nsIFrame* f1;
|
||||||
|
for (f1 = aFrame1; f1 && f1 != aKnownCommonAncestorHint;
|
||||||
|
f1 = GetParentOrPlaceholderFor(frameManager, f1)) {
|
||||||
|
frame1Ancestors.AppendElement(f1);
|
||||||
|
}
|
||||||
|
if (!f1 && aKnownCommonAncestorHint) {
|
||||||
|
// So, it turns out aKnownCommonAncestorHint was not an ancestor of f1. Oops.
|
||||||
|
// Never mind. We can continue as if aKnownCommonAncestorHint was null.
|
||||||
|
aKnownCommonAncestorHint = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoVoidArray frame2Ancestors;
|
||||||
|
nsIFrame* f2;
|
||||||
|
for (f2 = aFrame2; f2 && f2 != aKnownCommonAncestorHint;
|
||||||
|
f2 = GetParentOrPlaceholderFor(frameManager, f2)) {
|
||||||
|
frame2Ancestors.AppendElement(f2);
|
||||||
|
}
|
||||||
|
if (!f2 && aKnownCommonAncestorHint) {
|
||||||
|
// So, it turns out aKnownCommonAncestorHint was not an ancestor of f2.
|
||||||
|
// We need to retry with no common ancestor hint.
|
||||||
|
return GetClosestCommonAncestorViaPlaceholders(aFrame1, aFrame2, nsnull);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now frame1Ancestors and frame2Ancestors give us the parent frame chain
|
||||||
|
// up to aKnownCommonAncestorHint, or if that is null, up to and including
|
||||||
|
// the root frame. We need to walk from the end (i.e., the top of the
|
||||||
|
// frame (sub)tree) down to aFrame1/aFrame2 looking for the first difference.
|
||||||
|
nsIFrame* lastCommonFrame = aKnownCommonAncestorHint;
|
||||||
|
PRInt32 last1 = frame1Ancestors.Count() - 1;
|
||||||
|
PRInt32 last2 = frame2Ancestors.Count() - 1;
|
||||||
|
while (last1 >= 0 && last2 >= 0) {
|
||||||
|
nsIFrame* frame1 = NS_STATIC_CAST(nsIFrame*, frame1Ancestors.ElementAt(last1));
|
||||||
|
if (frame1 != frame2Ancestors.ElementAt(last2))
|
||||||
|
break;
|
||||||
|
lastCommonFrame = frame1;
|
||||||
|
last1--;
|
||||||
|
last2--;
|
||||||
|
}
|
||||||
|
return lastCommonFrame;
|
||||||
|
}
|
||||||
|
|||||||
@@ -431,6 +431,27 @@ public:
|
|||||||
*/
|
*/
|
||||||
static nsresult GetFontMetricsForFrame(nsIFrame* aFrame,
|
static nsresult GetFontMetricsForFrame(nsIFrame* aFrame,
|
||||||
nsIFontMetrics** aFontMetrics);
|
nsIFontMetrics** aFontMetrics);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If aFrame is an out of flow frame, return its placeholder, otherwise
|
||||||
|
* return its parent.
|
||||||
|
*/
|
||||||
|
static nsIFrame* GetParentOrPlaceholderFor(nsFrameManager* aFrameManager,
|
||||||
|
nsIFrame* aFrame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the closest common ancestor of aFrame1 and aFrame2, following
|
||||||
|
* out of flow frames to their placeholders instead of their parents. Returns
|
||||||
|
* nsnull if the frames are in different frame trees.
|
||||||
|
*
|
||||||
|
* @param aKnownCommonAncestorHint a frame that is believed to be on the
|
||||||
|
* ancestor chain of both aFrame1 and aFrame2. If null, or a frame that is
|
||||||
|
* not in fact on both ancestor chains, then this function will still return
|
||||||
|
* the correct result, but it will be slower.
|
||||||
|
*/
|
||||||
|
static nsIFrame*
|
||||||
|
GetClosestCommonAncestorViaPlaceholders(nsIFrame* aFrame1, nsIFrame* aFrame2,
|
||||||
|
nsIFrame* aKnownCommonAncestorHint);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsLayoutUtils_h__
|
#endif // nsLayoutUtils_h__
|
||||||
|
|||||||
@@ -3811,6 +3811,8 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
PRBool movedPastFloat = PR_FALSE;
|
PRBool movedPastFloat = PR_FALSE;
|
||||||
do {
|
do {
|
||||||
PRBool allowPullUp = aTryPull;
|
PRBool allowPullUp = aTryPull;
|
||||||
|
nsIContent* forceBreakInContent = nsnull;
|
||||||
|
PRInt32 forceBreakOffset = -1;
|
||||||
do {
|
do {
|
||||||
nsSpaceManager::SavedState spaceManagerState;
|
nsSpaceManager::SavedState spaceManagerState;
|
||||||
aState.mReflowState.mSpaceManager->PushState(&spaceManagerState);
|
aState.mReflowState.mSpaceManager->PushState(&spaceManagerState);
|
||||||
@@ -3827,17 +3829,30 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH));
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
|
if (forceBreakInContent) {
|
||||||
|
lineLayout.ForceBreakAtPosition(forceBreakInContent, forceBreakOffset);
|
||||||
|
}
|
||||||
rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
aKeepReflowGoing, &lineReflowStatus,
|
aKeepReflowGoing, &lineReflowStatus,
|
||||||
aUpdateMaximumWidth, aDamageDirtyArea,
|
aUpdateMaximumWidth, aDamageDirtyArea,
|
||||||
allowPullUp);
|
allowPullUp);
|
||||||
lineLayout.EndLineReflow();
|
lineLayout.EndLineReflow();
|
||||||
|
|
||||||
if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus ||
|
if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus ||
|
||||||
LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
|
LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
|
||||||
|
if (lineLayout.NeedsBackup()) {
|
||||||
|
NS_ASSERTION(!forceBreakInContent, "Backuping up twice; this should never be necessary");
|
||||||
|
// If there is no saved break position, then this will set
|
||||||
|
// set forceBreakInContent to null and we won't back up, which is
|
||||||
|
// correct.
|
||||||
|
forceBreakInContent = lineLayout.GetLastOptionalBreakPosition(&forceBreakOffset);
|
||||||
|
} else {
|
||||||
|
forceBreakInContent = nsnull;
|
||||||
|
}
|
||||||
// restore the space manager state
|
// restore the space manager state
|
||||||
aState.mReflowState.mSpaceManager->PopState(&spaceManagerState);
|
aState.mReflowState.mSpaceManager->PopState(&spaceManagerState);
|
||||||
// Clear out below-current-line-floats
|
// Clear out float lists
|
||||||
|
aState.mCurrentLineFloats.DeleteAll();
|
||||||
aState.mBelowCurrentLineFloats.DeleteAll();
|
aState.mBelowCurrentLineFloats.DeleteAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3887,6 +3902,13 @@ nsBlockFrame::PushTruncatedPlaceholderLine(nsBlockReflowState& aState,
|
|||||||
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
|
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static const char* LineReflowStatusNames[] = {
|
||||||
|
"LINE_REFLOW_OK", "LINE_REFLOW_STOP", "LINE_REFLOW_REDO_NO_PULL",
|
||||||
|
"LINE_REFLOW_REDO_NEXT_BAND", "LINE_REFLOW_TRUNCATED"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nsLineLayout& aLineLayout,
|
nsLineLayout& aLineLayout,
|
||||||
@@ -3953,9 +3975,18 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
// continuations
|
// continuations
|
||||||
PRBool isContinuingPlaceholders = PR_FALSE;
|
PRBool isContinuingPlaceholders = PR_FALSE;
|
||||||
|
|
||||||
|
if (impactedByFloats) {
|
||||||
|
// There is a soft break opportunity at the start of the line, because
|
||||||
|
// we can always move this line down below float(s).
|
||||||
|
if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0)) {
|
||||||
|
lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// need to repeatedly call GetChildCount here, because the child
|
// need to repeatedly call GetChildCount here, because the child
|
||||||
// count can change during the loop!
|
// count can change during the loop!
|
||||||
for (i = 0; i < aLine->GetChildCount(); i++) {
|
for (i = 0; LINE_REFLOW_OK == lineReflowStatus && i < aLine->GetChildCount();
|
||||||
|
i++, frame = frame->GetNextSibling()) {
|
||||||
if (IsContinuationPlaceholder(frame)) {
|
if (IsContinuationPlaceholder(frame)) {
|
||||||
isContinuingPlaceholders = PR_TRUE;
|
isContinuingPlaceholders = PR_TRUE;
|
||||||
}
|
}
|
||||||
@@ -3986,9 +4017,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
PushTruncatedPlaceholderLine(aState, aLine, lastPlaceholder, *aKeepReflowGoing);
|
PushTruncatedPlaceholderLine(aState, aLine, lastPlaceholder, *aKeepReflowGoing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
frame = frame->GetNextSibling();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't pull up new frames into lines with continuation placeholders
|
// Don't pull up new frames into lines with continuation placeholders
|
||||||
@@ -4024,6 +4053,20 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((lineReflowStatus == LINE_REFLOW_STOP || lineReflowStatus == LINE_REFLOW_OK) &&
|
||||||
|
!aLineLayout.HaveForcedBreakPosition() && aLineLayout.NeedsBackup()) {
|
||||||
|
// We need to try backing up to before a text run
|
||||||
|
PRInt32 offset;
|
||||||
|
nsIContent* breakContent = aLineLayout.GetLastOptionalBreakPosition(&offset);
|
||||||
|
if (breakContent) {
|
||||||
|
// We can back up!
|
||||||
|
lineReflowStatus = LINE_REFLOW_REDO_NO_PULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Don't try to force any breaking if we are going to retry
|
||||||
|
aLineLayout.ClearOptionalBreakPosition();
|
||||||
|
}
|
||||||
|
|
||||||
if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
|
if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
|
||||||
// This happens only when we have a line that is impacted by
|
// This happens only when we have a line that is impacted by
|
||||||
// floats and the first element in the line doesn't fit with
|
// floats and the first element in the line doesn't fit with
|
||||||
@@ -4084,6 +4127,11 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gNoisyReflow) {
|
||||||
|
printf("Line reflow status = %s\n", LineReflowStatusNames[lineReflowStatus]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
*aLineReflowStatus = lineReflowStatus;
|
*aLineReflowStatus = lineReflowStatus;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|||||||
@@ -218,20 +218,6 @@ nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
nsISelectionDisplay::DISPLAY_IMAGES);
|
nsISelectionDisplay::DISPLAY_IMAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsHTMLCanvasFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
|
||||||
{
|
|
||||||
// stolen from nsImageFrame.cpp
|
|
||||||
// images really CAN continue text runs, but the textFrame needs to be
|
|
||||||
// educated before we can indicate that it can. For now, we handle the fixing up
|
|
||||||
// of max element widths in nsLineLayout::VerticalAlignFrames, but hopefully
|
|
||||||
// this can be eliminated and the textFrame can be convinced to handle inlines
|
|
||||||
// that take up space in text runs.
|
|
||||||
|
|
||||||
aContinueTextRun = PR_FALSE;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHTMLCanvasFrame::GetContentForEvent(nsPresContext* aPresContext,
|
nsHTMLCanvasFrame::GetContentForEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent,
|
nsEvent* aEvent,
|
||||||
|
|||||||
@@ -65,9 +65,6 @@ public:
|
|||||||
const nsHTMLReflowState& aReflowState,
|
const nsHTMLReflowState& aReflowState,
|
||||||
nsReflowStatus& aStatus);
|
nsReflowStatus& aStatus);
|
||||||
|
|
||||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext,
|
NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent,
|
nsEvent* aEvent,
|
||||||
nsIContent** aContent);
|
nsIContent** aContent);
|
||||||
|
|||||||
@@ -1628,20 +1628,6 @@ nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsImageFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
|
||||||
{
|
|
||||||
// images really CAN continue text runs, but the textFrame needs to be
|
|
||||||
// educated before we can indicate that it can. For now, we handle the fixing up
|
|
||||||
// of max element widths in nsLineLayout::VerticalAlignFrames, but hopefully
|
|
||||||
// this can be eliminated and the textFrame can be convinced to handle inlines
|
|
||||||
// that take up space in text runs.
|
|
||||||
|
|
||||||
aContinueTextRun = PR_FALSE;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsImageFrame::GetContentForEvent(nsPresContext* aPresContext,
|
nsImageFrame::GetContentForEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent,
|
nsEvent* aEvent,
|
||||||
|
|||||||
@@ -110,9 +110,6 @@ public:
|
|||||||
const nsHTMLReflowState& aReflowState,
|
const nsHTMLReflowState& aReflowState,
|
||||||
nsReflowStatus& aStatus);
|
nsReflowStatus& aStatus);
|
||||||
|
|
||||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext,
|
NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext,
|
||||||
nsEvent* aEvent,
|
nsEvent* aEvent,
|
||||||
nsIContent** aContent);
|
nsIContent** aContent);
|
||||||
|
|||||||
@@ -680,7 +680,9 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext,
|
|||||||
nsLineLayout* lineLayout = aReflowState.mLineLayout;
|
nsLineLayout* lineLayout = aReflowState.mLineLayout;
|
||||||
PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
|
||||||
PRBool pushedFrame;
|
PRBool pushedFrame;
|
||||||
nsresult rv = lineLayout->ReflowFrame(aFrame, aStatus, nsnull, pushedFrame);
|
nsresult rv =
|
||||||
|
lineLayout->ReflowFrame(aFrame, aStatus, nsnull, pushedFrame);
|
||||||
|
|
||||||
/* This next block is for bug 28811
|
/* This next block is for bug 28811
|
||||||
Test the child frame for %-awareness,
|
Test the child frame for %-awareness,
|
||||||
and mark this frame with a bit if it is %-aware.
|
and mark this frame with a bit if it is %-aware.
|
||||||
|
|||||||
@@ -156,11 +156,15 @@ nsLineLayout::nsLineLayout(nsPresContext* aPresContext,
|
|||||||
: mPresContext(aPresContext),
|
: mPresContext(aPresContext),
|
||||||
mSpaceManager(aSpaceManager),
|
mSpaceManager(aSpaceManager),
|
||||||
mBlockReflowState(aOuterReflowState),
|
mBlockReflowState(aOuterReflowState),
|
||||||
|
mLastOptionalBreakContent(nsnull),
|
||||||
|
mForceBreakContent(nsnull),
|
||||||
|
mLastOptionalBreakContentOffset(-1),
|
||||||
|
mForceBreakContentOffset(-1),
|
||||||
|
mTrailingTextFrame(nsnull),
|
||||||
mBlockRS(nsnull),/* XXX temporary */
|
mBlockRS(nsnull),/* XXX temporary */
|
||||||
mMinLineHeight(0),
|
mMinLineHeight(0),
|
||||||
mComputeMaxElementWidth(aComputeMaxElementWidth),
|
mComputeMaxElementWidth(aComputeMaxElementWidth),
|
||||||
mTextIndent(0),
|
mTextIndent(0)
|
||||||
mWordFrames(0)
|
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsLineLayout);
|
MOZ_COUNT_CTOR(nsLineLayout);
|
||||||
|
|
||||||
@@ -195,8 +199,6 @@ nsLineLayout::~nsLineLayout()
|
|||||||
|
|
||||||
NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user");
|
NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user");
|
||||||
|
|
||||||
delete mWordFrames; // operator delete for this class just returns
|
|
||||||
|
|
||||||
// PL_FreeArenaPool takes our memory and puts in on a global free list so
|
// PL_FreeArenaPool takes our memory and puts in on a global free list so
|
||||||
// that the next time an arena makes an allocation it will not have to go
|
// that the next time an arena makes an allocation it will not have to go
|
||||||
// all the way down to malloc. This is desirable as this class is created
|
// all the way down to malloc. This is desirable as this class is created
|
||||||
@@ -210,22 +212,6 @@ nsLineLayout::~nsLineLayout()
|
|||||||
PL_FinishArenaPool(&mArena);
|
PL_FinishArenaPool(&mArena);
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
|
||||||
nsLineLayout::ArenaDeque::operator new(size_t aSize, PLArenaPool &aPool)
|
|
||||||
{
|
|
||||||
void *mem;
|
|
||||||
|
|
||||||
PL_ARENA_ALLOCATE(mem, &aPool, aSize);
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool nsLineLayout::AllocateDeque()
|
|
||||||
{
|
|
||||||
mWordFrames = new(mArena) ArenaDeque;
|
|
||||||
|
|
||||||
return mWordFrames != nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find out if the frame has a non-null prev-in-flow, i.e., whether it
|
// Find out if the frame has a non-null prev-in-flow, i.e., whether it
|
||||||
// is a continuation.
|
// is a continuation.
|
||||||
inline PRBool
|
inline PRBool
|
||||||
@@ -282,8 +268,6 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
|||||||
mSpanDepth = 0;
|
mSpanDepth = 0;
|
||||||
mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
|
mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
|
||||||
|
|
||||||
ForgetWordFrames();
|
|
||||||
|
|
||||||
PerSpanData* psd;
|
PerSpanData* psd;
|
||||||
NewPerSpanData(&psd);
|
NewPerSpanData(&psd);
|
||||||
mCurrentSpan = mRootSpan = psd;
|
mCurrentSpan = mRootSpan = psd;
|
||||||
@@ -313,7 +297,7 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
|||||||
|
|
||||||
// If this is the first line of a block then see if the text-indent
|
// If this is the first line of a block then see if the text-indent
|
||||||
// property amounts to anything.
|
// property amounts to anything.
|
||||||
|
|
||||||
if (0 == mLineNumber && !HasPrevInFlow(mBlockReflowState->frame)) {
|
if (0 == mLineNumber && !HasPrevInFlow(mBlockReflowState->frame)) {
|
||||||
nscoord indent = 0;
|
nscoord indent = 0;
|
||||||
nsStyleUnit unit = mStyleText->mTextIndent.GetUnit();
|
nsStyleUnit unit = mStyleText->mTextIndent.GetUnit();
|
||||||
@@ -936,17 +920,16 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
|||||||
|
|
||||||
// We want to guarantee that we always make progress when
|
// We want to guarantee that we always make progress when
|
||||||
// formatting. Therefore, if the object being placed on the line is
|
// formatting. Therefore, if the object being placed on the line is
|
||||||
// too big for the line, but it is the only thing on the line
|
// too big for the line, but it is the only thing on the line and is not
|
||||||
// (including counting floats) then we go ahead and place it
|
// impacted by a float, then we go ahead and place it anyway. (If the line
|
||||||
// anyway. Its also true that if the object is a part of a larger
|
// is impacted by one or more floats, then it is safe to break because
|
||||||
// object (a multiple frame word) then we will place it on the line
|
// we can move the line down below float(s).)
|
||||||
// too.
|
|
||||||
//
|
//
|
||||||
// Capture this state *before* we reflow the frame in case it clears
|
// Capture this state *before* we reflow the frame in case it clears
|
||||||
// the state out. We need to know how to treat the current frame
|
// the state out. We need to know how to treat the current frame
|
||||||
// when breaking.
|
// when breaking.
|
||||||
PRBool notSafeToBreak = CanPlaceFloatNow() || InWord();
|
PRBool notSafeToBreak = CanPlaceFloatNow() && !GetFlag(LL_IMPACTEDBYFLOATS);
|
||||||
|
|
||||||
// Apply start margins (as appropriate) to the frame computing the
|
// Apply start margins (as appropriate) to the frame computing the
|
||||||
// new starting x,y coordinates for the frame.
|
// new starting x,y coordinates for the frame.
|
||||||
ApplyStartMargin(pfd, reflowState);
|
ApplyStartMargin(pfd, reflowState);
|
||||||
@@ -991,32 +974,36 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
|||||||
#endif // IBMBIDI
|
#endif // IBMBIDI
|
||||||
|
|
||||||
nsIAtom* frameType = aFrame->GetType();
|
nsIAtom* frameType = aFrame->GetType();
|
||||||
|
|
||||||
|
PRInt32 savedOptionalBreakOffset;
|
||||||
|
nsIContent* savedOptionalBreakContent =
|
||||||
|
GetLastOptionalBreakPosition(&savedOptionalBreakOffset);
|
||||||
|
|
||||||
rv = aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
|
rv = aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
NS_WARNING( "Reflow of frame failed in nsLineLayout" );
|
NS_WARNING( "Reflow of frame failed in nsLineLayout" );
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
|
pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
|
||||||
pfd->mJustificationNumLetters = mTextJustificationNumLetters;
|
pfd->mJustificationNumLetters = mTextJustificationNumLetters;
|
||||||
|
|
||||||
// XXX See if the frame is a placeholderFrame and if it is process
|
// XXX See if the frame is a placeholderFrame and if it is process
|
||||||
// the float.
|
// the float.
|
||||||
|
PRBool placedFloat = PR_FALSE;
|
||||||
if (frameType) {
|
if (frameType) {
|
||||||
if (nsLayoutAtoms::placeholderFrame == frameType) {
|
if (nsLayoutAtoms::placeholderFrame == frameType) {
|
||||||
pfd->SetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE, PR_TRUE);
|
pfd->SetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE, PR_TRUE);
|
||||||
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
|
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
|
||||||
if (outOfFlowFrame) {
|
if (outOfFlowFrame) {
|
||||||
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
|
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
|
||||||
PRBool didPlace;
|
|
||||||
if (eReflowReason_Incremental == reason) {
|
if (eReflowReason_Incremental == reason) {
|
||||||
didPlace = InitFloat(placeholder, aReflowStatus);
|
placedFloat = InitFloat(placeholder, aReflowStatus);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
didPlace = AddFloat(placeholder, aReflowStatus);
|
placedFloat = AddFloat(placeholder, aReflowStatus);
|
||||||
}
|
}
|
||||||
if (!didPlace) {
|
if (!placedFloat) {
|
||||||
aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
||||||
}
|
}
|
||||||
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
|
if (outOfFlowFrame->GetType() == nsLayoutAtoms::letterFrame) {
|
||||||
@@ -1164,9 +1151,15 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether this frame breaks up text runs. All frames break up text
|
||||||
|
// runs (hence return false here) except for text frames and inline containers.
|
||||||
|
PRBool continuingTextRun;
|
||||||
|
aFrame->CanContinueTextRun(continuingTextRun);
|
||||||
|
|
||||||
// See if we can place the frame. If we can't fit it, then we
|
// See if we can place the frame. If we can't fit it, then we
|
||||||
// return now.
|
// return now.
|
||||||
if (CanPlaceFrame(pfd, reflowState, notSafeToBreak, metrics, aReflowStatus)) {
|
if (CanPlaceFrame(pfd, reflowState, notSafeToBreak, continuingTextRun,
|
||||||
|
metrics, aReflowStatus)) {
|
||||||
// Place the frame, updating aBounds with the final size and
|
// Place the frame, updating aBounds with the final size and
|
||||||
// location. Then apply the bottom+right margins (as
|
// location. Then apply the bottom+right margins (as
|
||||||
// appropriate) to the frame.
|
// appropriate) to the frame.
|
||||||
@@ -1178,16 +1171,34 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
|||||||
// so do most of it now.
|
// so do most of it now.
|
||||||
VerticalAlignFrames(span);
|
VerticalAlignFrames(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!continuingTextRun) {
|
||||||
|
SetFlag(LL_INWORD, PR_FALSE);
|
||||||
|
mTrailingTextFrame = nsnull;
|
||||||
|
if (!psd->mNoWrap && (!CanPlaceFloatNow() || placedFloat)) {
|
||||||
|
// record soft break opportunity after this content that can't be
|
||||||
|
// part of a text run. This is not a text frame so we know
|
||||||
|
// that offset PR_INT32_MAX means "after the content".
|
||||||
|
if (NotifyOptionalBreakPosition(aFrame->GetContent(), PR_INT32_MAX)) {
|
||||||
|
// If this returns true then we are being told to actually break here.
|
||||||
|
aReflowStatus = NS_INLINE_LINE_BREAK_AFTER(aReflowStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PushFrame(aFrame);
|
PushFrame(aFrame);
|
||||||
aPushedFrame = PR_TRUE;
|
aPushedFrame = PR_TRUE;
|
||||||
|
// Undo any saved break positions that the frame might have told us about,
|
||||||
|
// since we didn't end up placing it
|
||||||
|
RestoreSavedBreakPosition(savedOptionalBreakContent,
|
||||||
|
savedOptionalBreakOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PushFrame(aFrame);
|
PushFrame(aFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
nsFrame::IndentBy(stdout, mSpanDepth);
|
nsFrame::IndentBy(stdout, mSpanDepth);
|
||||||
printf("End ReflowFrame ");
|
printf("End ReflowFrame ");
|
||||||
@@ -1262,6 +1273,7 @@ PRBool
|
|||||||
nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
const nsHTMLReflowState& aReflowState,
|
const nsHTMLReflowState& aReflowState,
|
||||||
PRBool aNotSafeToBreak,
|
PRBool aNotSafeToBreak,
|
||||||
|
PRBool aFrameCanContinueTextRun,
|
||||||
nsHTMLReflowMetrics& aMetrics,
|
nsHTMLReflowMetrics& aMetrics,
|
||||||
nsReflowStatus& aStatus)
|
nsReflowStatus& aStatus)
|
||||||
{
|
{
|
||||||
@@ -1297,6 +1309,9 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
|||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool ltr = NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection;
|
||||||
|
nscoord endMargin = ltr ? pfd->mMargin.right : pfd->mMargin.left;
|
||||||
|
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
if (nsnull != psd->mFrame) {
|
if (nsnull != psd->mFrame) {
|
||||||
nsFrame::ListTag(stdout, psd->mFrame->mFrame);
|
nsFrame::ListTag(stdout, psd->mFrame->mFrame);
|
||||||
@@ -1306,13 +1321,12 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
|||||||
}
|
}
|
||||||
printf(": aNotSafeToBreak=%s frame=", aNotSafeToBreak ? "true" : "false");
|
printf(": aNotSafeToBreak=%s frame=", aNotSafeToBreak ? "true" : "false");
|
||||||
nsFrame::ListTag(stdout, pfd->mFrame);
|
nsFrame::ListTag(stdout, pfd->mFrame);
|
||||||
printf(" frameWidth=%d\n", pfd->mBounds.XMost() + rightMargin - psd->mX);
|
printf(" frameWidth=%d\n", pfd->mBounds.XMost() + endMargin - psd->mX);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set outside to PR_TRUE if the result of the reflow leads to the
|
// Set outside to PR_TRUE if the result of the reflow leads to the
|
||||||
// frame sticking outside of our available area.
|
// frame sticking outside of our available area.
|
||||||
PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
|
PRBool outside = pfd->mBounds.XMost() + endMargin > psd->mRightEdge;
|
||||||
PRBool outside = pfd->mBounds.XMost() + (ltr ? pfd->mMargin.right : pfd->mMargin.left) > psd->mRightEdge;
|
|
||||||
if (!outside) {
|
if (!outside) {
|
||||||
// If it fits, it fits
|
// If it fits, it fits
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
@@ -1342,75 +1356,20 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (aNotSafeToBreak) {
|
if (aNotSafeToBreak) {
|
||||||
// There are no frames on the line or we are in the first word on
|
// There are no frames on the line that take up width and the line is
|
||||||
// the line. If the line isn't impacted by a float then the
|
// not impacted by floats, so we must allow the current frame to be
|
||||||
// current frame fits.
|
// placed on the line
|
||||||
if (!GetFlag(LL_IMPACTEDBYFLOATS)) {
|
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
printf(" ==> not-safe and not-impacted fits: ");
|
printf(" ==> not-safe and not-impacted fits: ");
|
||||||
while (nsnull != psd) {
|
while (nsnull != psd) {
|
||||||
printf("<psd=%p x=%d left=%d> ", psd, psd->mX, psd->mLeftEdge);
|
printf("<psd=%p x=%d left=%d> ", psd, psd->mX, psd->mLeftEdge);
|
||||||
psd = psd->mParent;
|
psd = psd->mParent;
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
|
||||||
else if (GetFlag(LL_LASTFLOATWASLETTERFRAME)) {
|
|
||||||
// Another special case: see if the float is a letter
|
|
||||||
// frame. If it is, then allow the frame next to it to fit.
|
|
||||||
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
|
||||||
// This must be the first piece of non-empty text (because
|
|
||||||
// aNotSafeToBreak is true) or it's a piece of text that is
|
|
||||||
// part of a larger word.
|
|
||||||
pfd->SetFlag(PFD_ISSTICKY, PR_TRUE);
|
|
||||||
}
|
|
||||||
else if (pfd->mSpan) {
|
|
||||||
PerFrameData* pf = pfd->mSpan->mFirstFrame;
|
|
||||||
while (pf) {
|
|
||||||
if (pf->GetFlag(PFD_ISSTICKY)) {
|
|
||||||
// If one of the spans children was sticky then the span
|
|
||||||
// itself is sticky.
|
|
||||||
pfd->SetFlag(PFD_ISSTICKY, PR_TRUE);
|
|
||||||
}
|
|
||||||
pf = pf->mNext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd->GetFlag(PFD_ISSTICKY)) {
|
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
|
||||||
printf(" ==> last float was letter frame && frame is sticky\n");
|
|
||||||
#endif
|
|
||||||
return PR_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a piece of text inside a letter frame...
|
|
||||||
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
|
||||||
if (psd->mFrame && psd->mFrame->GetFlag(PFD_ISLETTERFRAME)) {
|
|
||||||
nsIFrame* prevInFlow = psd->mFrame->mFrame->GetPrevInFlow();
|
|
||||||
if (prevInFlow) {
|
|
||||||
nsIFrame* prevPrevInFlow = prevInFlow->GetPrevInFlow();
|
|
||||||
if (!prevPrevInFlow) {
|
|
||||||
// And it's the first continuation of the letter frame...
|
|
||||||
// Then make sure that the text fits
|
|
||||||
return PR_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pfd->GetFlag(PFD_ISLETTERFRAME)) {
|
|
||||||
// If this is the first continuation of the letter frame...
|
|
||||||
nsIFrame* prevInFlow = pfd->mFrame->GetPrevInFlow();
|
|
||||||
if (prevInFlow) {
|
|
||||||
nsIFrame* prevPrevInFlow = prevInFlow->GetPrevInFlow();
|
|
||||||
if (!prevPrevInFlow) {
|
|
||||||
return PR_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special check for span frames
|
// Special check for span frames
|
||||||
if (pfd->mSpan && pfd->mSpan->mContainsFloat) {
|
if (pfd->mSpan && pfd->mSpan->mContainsFloat) {
|
||||||
// If the span either directly or indirectly contains a float then
|
// If the span either directly or indirectly contains a float then
|
||||||
@@ -1439,6 +1398,24 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
|||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aFrameCanContinueTextRun) {
|
||||||
|
// Let it fit, but we reserve the right to roll back
|
||||||
|
// to before the text run! Note that we usually won't get here because
|
||||||
|
// a text frame will break itself to avoid exceeding the available width.
|
||||||
|
// We'll only get here for text frames that couldn't break early enough.
|
||||||
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
|
printf(" ==> placing overflowing textrun, requesting backup\n");
|
||||||
|
#endif
|
||||||
|
if (!mLastOptionalBreakContent) {
|
||||||
|
// Nowhere to roll back to, so make this fit
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have something to roll back to. So, signal that we will to roll back,
|
||||||
|
// and fall through to not place this frame.
|
||||||
|
SetFlag(LL_NEEDBACKUP, PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
printf(" ==> didn't fit\n");
|
printf(" ==> didn't fit\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -3062,107 +3039,6 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
|||||||
aCombinedArea = combinedAreaResult;
|
aCombinedArea = combinedAreaResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsLineLayout::ForgetWordFrame(nsIFrame* aFrame)
|
|
||||||
{
|
|
||||||
if (mWordFrames && 0 != mWordFrames->GetSize()) {
|
|
||||||
NS_ASSERTION((void*)aFrame == mWordFrames->PeekFront(), "forget-word-frame");
|
|
||||||
mWordFrames->PopFront();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIFrame*
|
|
||||||
nsLineLayout::FindNextText(nsPresContext* aPresContext, nsIFrame* aFrame)
|
|
||||||
{
|
|
||||||
// Grovel through the frame hierarchy to find a text frame that is
|
|
||||||
// "adjacent" to aFrame.
|
|
||||||
|
|
||||||
// So this is kind of funky. During reflow, overflow frames will
|
|
||||||
// have their parent pointers set up lazily. We assume that, on
|
|
||||||
// entry, aFrame has its parent pointer set correctly (as do all of
|
|
||||||
// its ancestors). Starting from that, we need to make sure that as
|
|
||||||
// we traverse through frames trying to find the next text frame, we
|
|
||||||
// leave the frames with their parent pointers set correctly, so the
|
|
||||||
// *next* time we come through here, we're good to go.
|
|
||||||
|
|
||||||
// Build a path from the enclosing block frame down to aFrame. We'll
|
|
||||||
// use this to walk the frame tree. (XXXwaterson if I was clever, I
|
|
||||||
// wouldn't need to build this up before hand, and could incorporate
|
|
||||||
// this logic into the walking code directly.)
|
|
||||||
nsAutoVoidArray stack;
|
|
||||||
for (;;) {
|
|
||||||
stack.InsertElementAt(aFrame, 0);
|
|
||||||
|
|
||||||
aFrame = aFrame->GetParent();
|
|
||||||
|
|
||||||
NS_ASSERTION(aFrame, "wow, no block frame found");
|
|
||||||
if (! aFrame)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (NS_STYLE_DISPLAY_INLINE != aFrame->GetStyleDisplay()->mDisplay)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using the path we've built up, walk the frame tree looking for
|
|
||||||
// the text frame that follows aFrame.
|
|
||||||
PRInt32 count;
|
|
||||||
while ((count = stack.Count()) != 0) {
|
|
||||||
PRInt32 lastIndex = count - 1;
|
|
||||||
nsIFrame* top = NS_STATIC_CAST(nsIFrame*, stack.ElementAt(lastIndex));
|
|
||||||
|
|
||||||
// If this is a frame that'll break a word, then bail.
|
|
||||||
PRBool canContinue;
|
|
||||||
top->CanContinueTextRun(canContinue);
|
|
||||||
if (! canContinue)
|
|
||||||
return nsnull;
|
|
||||||
|
|
||||||
// Advance to top's next sibling
|
|
||||||
nsIFrame* next = top->GetNextSibling();
|
|
||||||
|
|
||||||
if (! next) {
|
|
||||||
// No more siblings. Pop the top element to walk back up the
|
|
||||||
// frame tree.
|
|
||||||
stack.RemoveElementAt(lastIndex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know top's parent is good, but next's might not be. So let's
|
|
||||||
// set it to be sure.
|
|
||||||
next->SetParent(top->GetParent());
|
|
||||||
|
|
||||||
// Save next at the top of the stack...
|
|
||||||
stack.ReplaceElementAt(next, lastIndex);
|
|
||||||
|
|
||||||
// ...and prowl down to next's deepest child. We'll need to check
|
|
||||||
// for potential run-busters "on the way down", too.
|
|
||||||
for (;;) {
|
|
||||||
next->CanContinueTextRun(canContinue);
|
|
||||||
if (! canContinue)
|
|
||||||
return nsnull;
|
|
||||||
|
|
||||||
nsIFrame* child = next->GetFirstChild(nsnull);
|
|
||||||
|
|
||||||
if (! child)
|
|
||||||
break;
|
|
||||||
|
|
||||||
stack.AppendElement(child);
|
|
||||||
next = child;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore continuing frames
|
|
||||||
if (HasPrevInFlow(next))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If this is a text frame, return it.
|
|
||||||
if (nsLayoutAtoms::textFrame == next->GetType())
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here, then there are no more text frames in this block.
|
|
||||||
return nsnull;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::TreatFrameAsBlock(nsIFrame* aFrame)
|
nsLineLayout::TreatFrameAsBlock(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,6 +56,8 @@
|
|||||||
#include "nsBlockReflowState.h"
|
#include "nsBlockReflowState.h"
|
||||||
#include "plarena.h"
|
#include "plarena.h"
|
||||||
|
|
||||||
|
class nsBlockFrame;
|
||||||
|
|
||||||
class nsSpaceManager;
|
class nsSpaceManager;
|
||||||
class nsPlaceholderFrame;
|
class nsPlaceholderFrame;
|
||||||
struct nsStyleText;
|
struct nsStyleText;
|
||||||
@@ -68,14 +70,6 @@ public:
|
|||||||
PRBool aComputeMaxElementWidth);
|
PRBool aComputeMaxElementWidth);
|
||||||
~nsLineLayout();
|
~nsLineLayout();
|
||||||
|
|
||||||
class ArenaDeque : public nsDeque
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ArenaDeque() : nsDeque(nsnull) {}
|
|
||||||
void *operator new(size_t, PLArenaPool &pool);
|
|
||||||
void operator delete(void *) {} // Dont do anything. Its Arena memory
|
|
||||||
};
|
|
||||||
|
|
||||||
void Init(nsBlockReflowState* aState, nscoord aMinLineHeight,
|
void Init(nsBlockReflowState* aState, nscoord aMinLineHeight,
|
||||||
PRInt32 aLineNumber) {
|
PRInt32 aLineNumber) {
|
||||||
mBlockRS = aState;
|
mBlockRS = aState;
|
||||||
@@ -156,6 +150,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
#define LL_ENDSINWHITESPACE 0x00000001
|
#define LL_ENDSINWHITESPACE 0x00000001
|
||||||
#define LL_UNDERSTANDSNWHITESPACE 0x00000002
|
#define LL_UNDERSTANDSNWHITESPACE 0x00000002
|
||||||
|
#define LL_INWORD 0x00000004
|
||||||
#define LL_FIRSTLETTERSTYLEOK 0x00000008
|
#define LL_FIRSTLETTERSTYLEOK 0x00000008
|
||||||
#define LL_ISTOPOFPAGE 0x00000010
|
#define LL_ISTOPOFPAGE 0x00000010
|
||||||
#define LL_UPDATEDBAND 0x00000020
|
#define LL_UPDATEDBAND 0x00000020
|
||||||
@@ -169,7 +164,9 @@ protected:
|
|||||||
// large, e.g., if a large word-spacing is set). LL should not be misled into
|
// large, e.g., if a large word-spacing is set). LL should not be misled into
|
||||||
// placing something where the whitespace was trimmed. See bug 329987.
|
// placing something where the whitespace was trimmed. See bug 329987.
|
||||||
#define LL_LINEENDSINSOFTBR 0x00000400
|
#define LL_LINEENDSINSOFTBR 0x00000400
|
||||||
#define LL_LASTFLAG LL_LINEENDSINSOFTBR
|
#define LL_NEEDBACKUP 0x00000800
|
||||||
|
#define LL_LASTTEXTFRAME_WRAPPINGENABLED 0x00001000
|
||||||
|
#define LL_LASTFLAG LL_LASTTEXTFRAME_WRAPPINGENABLED
|
||||||
|
|
||||||
PRUint16 mFlags;
|
PRUint16 mFlags;
|
||||||
|
|
||||||
@@ -215,25 +212,6 @@ public:
|
|||||||
mTextJustificationNumLetters = aNumLetters;
|
mTextJustificationNumLetters = aNumLetters;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordWordFrame(nsIFrame* aWordFrame) {
|
|
||||||
if(mWordFrames || AllocateDeque())
|
|
||||||
mWordFrames->Push(aWordFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool InWord() const {
|
|
||||||
return mWordFrames && 0 != mWordFrames->GetSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForgetWordFrame(nsIFrame* aFrame);
|
|
||||||
|
|
||||||
void ForgetWordFrames() {
|
|
||||||
if(mWordFrames) {
|
|
||||||
mWordFrames->Empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIFrame* FindNextText(nsPresContext* aPresContext, nsIFrame* aFrame);
|
|
||||||
|
|
||||||
PRBool CanPlaceFloatNow() const;
|
PRBool CanPlaceFloatNow() const;
|
||||||
|
|
||||||
PRBool LineIsBreakable() const;
|
PRBool LineIsBreakable() const;
|
||||||
@@ -279,6 +257,44 @@ public:
|
|||||||
return mBlockRS->AddFloat(*this, aFrame, PR_FALSE, aReflowStatus);
|
return mBlockRS->AddFloat(*this, aFrame, PR_FALSE, aReflowStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InWord is true when the last text frame reflowed ended in non-whitespace
|
||||||
|
* (so it has content that might form a word with subsequent text). The word width
|
||||||
|
* is the width of contiguous text up to the end of that last word, possibly
|
||||||
|
* including words from previous frames.
|
||||||
|
*
|
||||||
|
* If GetTrailingTextFrame is null then InWord will be false.
|
||||||
|
*/
|
||||||
|
PRBool InWord(nscoord* aWordWidth) {
|
||||||
|
if (!GetFlag(LL_INWORD))
|
||||||
|
return PR_FALSE;
|
||||||
|
*aWordWidth = mWordWidth;
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
void SetInWord(PRBool aInWord, nscoord aWordWidth) {
|
||||||
|
SetFlag(LL_INWORD, aInWord);
|
||||||
|
mWordWidth = aWordWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the last content placed on the line (not counting inline containers)
|
||||||
|
* was text, and can form a contiguous text flow with the next content to be
|
||||||
|
* placed, and is not just a frame of all-skipped whitespace, this is the
|
||||||
|
* frame for that last content ... otherwise it's null.
|
||||||
|
*
|
||||||
|
* @param aWrappingEnabled whether that text had word-wrapping enabled
|
||||||
|
* (white-space:normal or -moz-pre-wrap)
|
||||||
|
*/
|
||||||
|
nsIFrame* GetTrailingTextFrame(PRBool* aWrappingEnabled) {
|
||||||
|
*aWrappingEnabled = GetFlag(LL_LASTTEXTFRAME_WRAPPINGENABLED);
|
||||||
|
return mTrailingTextFrame;
|
||||||
|
}
|
||||||
|
void SetTrailingTextFrame(nsIFrame* aFrame, PRBool aWrappingEnabled)
|
||||||
|
{
|
||||||
|
mTrailingTextFrame = aFrame;
|
||||||
|
SetFlag(LL_LASTTEXTFRAME_WRAPPINGENABLED, aWrappingEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
PRBool GetFirstLetterStyleOK() const {
|
PRBool GetFirstLetterStyleOK() const {
|
||||||
@@ -307,12 +323,99 @@ public:
|
|||||||
|
|
||||||
nsPresContext* mPresContext;
|
nsPresContext* mPresContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record where an optional break could have been placed. During line reflow,
|
||||||
|
* frames containing optional break points (e.g., whitespace in text frames)
|
||||||
|
* can call SetLastOptionalBreakPosition to record where a break could
|
||||||
|
* have been made, but wasn't because there appeared to be enough room
|
||||||
|
* to place more content on the line. For non-text frames, offset 0 means
|
||||||
|
* before the content, offset PR_INT32_MAX means after the content.
|
||||||
|
*
|
||||||
|
* Currently this is used to handle cases where a single word comprises
|
||||||
|
* multiple frames, and the first frame fits on the line but the whole word
|
||||||
|
* doesn't. We look back to the last optional break position and
|
||||||
|
* reflow the whole line again, forcing a break at that position. The last
|
||||||
|
* optional break position could be in a text frame or else after a frame
|
||||||
|
* that cannot be part of a text run, so those are the positions we record.
|
||||||
|
*
|
||||||
|
* It is imperative that this only gets called for break points that
|
||||||
|
* are within the available width.
|
||||||
|
*
|
||||||
|
* @return PR_TRUE if we are actually reflowing with forced break position and we
|
||||||
|
* should break here
|
||||||
|
*/
|
||||||
|
PRBool NotifyOptionalBreakPosition(nsIContent* aContent, PRInt32 aOffset) {
|
||||||
|
NS_ASSERTION(!GetFlag(LL_NEEDBACKUP),
|
||||||
|
"Shouldn't be updating the break position after we've already flagged an overrun");
|
||||||
|
mLastOptionalBreakContent = aContent;
|
||||||
|
mLastOptionalBreakContentOffset = aOffset;
|
||||||
|
return aContent && mForceBreakContent == aContent &&
|
||||||
|
mForceBreakContentOffset == aOffset;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Like NotifyOptionalBreakPosition, but here it's OK for LL_NEEDBACKUP
|
||||||
|
* to be set, because the caller is merely pruning some saved break position(s)
|
||||||
|
* that are actually not feasible.
|
||||||
|
*/
|
||||||
|
void RestoreSavedBreakPosition(nsIContent* aContent, PRInt32 aOffset) {
|
||||||
|
mLastOptionalBreakContent = aContent;
|
||||||
|
mLastOptionalBreakContentOffset = aOffset;
|
||||||
|
}
|
||||||
|
void ClearOptionalBreakPosition() {
|
||||||
|
mLastOptionalBreakContent = nsnull;
|
||||||
|
mLastOptionalBreakContentOffset = -1;
|
||||||
|
}
|
||||||
|
// Retrieve last set optional break position. When this returns null, no
|
||||||
|
// optional break has been recorded (which means that the line can't break yet).
|
||||||
|
nsIContent* GetLastOptionalBreakPosition(PRInt32* aOffset) {
|
||||||
|
*aOffset = mLastOptionalBreakContentOffset;
|
||||||
|
return mLastOptionalBreakContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether frames overflowed the available width and CanPlaceFrame
|
||||||
|
* requested backing up to a saved break position.
|
||||||
|
*/
|
||||||
|
PRBool NeedsBackup() { return GetFlag(LL_NEEDBACKUP); }
|
||||||
|
|
||||||
|
// Line layout may place too much content on a line, overflowing its available
|
||||||
|
// width. When that happens, if SetLastOptionalBreakPosition has been
|
||||||
|
// used to record an optional break that wasn't taken, we can reflow the line
|
||||||
|
// again and force the break to happen at that point (i.e., backtracking
|
||||||
|
// to the last choice point).
|
||||||
|
|
||||||
|
// Record that we want to break at the given content+offset (which
|
||||||
|
// should have been previously returned by GetLastOptionalBreakPosition
|
||||||
|
// from another nsLineLayout).
|
||||||
|
void ForceBreakAtPosition(nsIContent* aContent, PRInt32 aOffset) {
|
||||||
|
mForceBreakContent = aContent;
|
||||||
|
mForceBreakContentOffset = aOffset;
|
||||||
|
}
|
||||||
|
PRBool HaveForcedBreakPosition() { return mForceBreakContent != nsnull; }
|
||||||
|
PRInt32 GetForcedBreakPosition(nsIContent* aContent) {
|
||||||
|
return mForceBreakContent == aContent ? mForceBreakContentOffset : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This can't be null. It usually returns a block frame but may return
|
||||||
|
* some other kind of frame when inline frames are reflowed in a non-block
|
||||||
|
* context (e.g. MathML).
|
||||||
|
*/
|
||||||
|
nsIFrame* GetLineContainerFrame() { return mBlockReflowState->frame; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This state is constant for a given block frame doing line layout
|
// This state is constant for a given block frame doing line layout
|
||||||
nsSpaceManager* mSpaceManager;
|
nsSpaceManager* mSpaceManager;
|
||||||
const nsStyleText* mStyleText; // for the block
|
const nsStyleText* mStyleText; // for the block
|
||||||
const nsHTMLReflowState* mBlockReflowState;
|
const nsHTMLReflowState* mBlockReflowState;
|
||||||
|
|
||||||
|
nsIContent* mLastOptionalBreakContent;
|
||||||
|
nsIContent* mForceBreakContent;
|
||||||
|
PRInt32 mLastOptionalBreakContentOffset;
|
||||||
|
PRInt32 mForceBreakContentOffset;
|
||||||
|
|
||||||
|
nsIFrame* mTrailingTextFrame;
|
||||||
|
|
||||||
// XXX remove this when landing bug 154892 (splitting absolute positioned frames)
|
// XXX remove this when landing bug 154892 (splitting absolute positioned frames)
|
||||||
friend class nsInlineFrame;
|
friend class nsInlineFrame;
|
||||||
|
|
||||||
@@ -333,14 +436,13 @@ protected:
|
|||||||
nsIFrame* mFirstLetterFrame;
|
nsIFrame* mFirstLetterFrame;
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
PRInt32 mColumn;
|
PRInt32 mColumn;
|
||||||
|
nscoord mWordWidth;
|
||||||
PRInt32 mTextJustificationNumSpaces;
|
PRInt32 mTextJustificationNumSpaces;
|
||||||
PRInt32 mTextJustificationNumLetters;
|
PRInt32 mTextJustificationNumLetters;
|
||||||
|
|
||||||
nsLineBox* mLineBox;
|
nsLineBox* mLineBox;
|
||||||
|
|
||||||
PRInt32 mTotalPlacedFrames;
|
PRInt32 mTotalPlacedFrames;
|
||||||
ArenaDeque *mWordFrames;
|
|
||||||
PRBool AllocateDeque();
|
|
||||||
|
|
||||||
nscoord mTopEdge;
|
nscoord mTopEdge;
|
||||||
nscoord mMaxTopBoxHeight;
|
nscoord mMaxTopBoxHeight;
|
||||||
@@ -395,7 +497,6 @@ protected:
|
|||||||
#define PFD_ISNONEMPTYTEXTFRAME 0x00000004
|
#define PFD_ISNONEMPTYTEXTFRAME 0x00000004
|
||||||
#define PFD_ISNONWHITESPACETEXTFRAME 0x00000008
|
#define PFD_ISNONWHITESPACETEXTFRAME 0x00000008
|
||||||
#define PFD_ISLETTERFRAME 0x00000010
|
#define PFD_ISLETTERFRAME 0x00000010
|
||||||
#define PFD_ISSTICKY 0x00000020
|
|
||||||
#define PFD_ISBULLET 0x00000040
|
#define PFD_ISBULLET 0x00000040
|
||||||
#define PFD_SKIPWHENTRIMMINGWHITESPACE 0x00000080
|
#define PFD_SKIPWHENTRIMMINGWHITESPACE 0x00000080
|
||||||
#define PFD_LASTFLAG PFD_SKIPWHENTRIMMINGWHITESPACE
|
#define PFD_LASTFLAG PFD_SKIPWHENTRIMMINGWHITESPACE
|
||||||
@@ -497,6 +598,7 @@ protected:
|
|||||||
PRBool CanPlaceFrame(PerFrameData* pfd,
|
PRBool CanPlaceFrame(PerFrameData* pfd,
|
||||||
const nsHTMLReflowState& aReflowState,
|
const nsHTMLReflowState& aReflowState,
|
||||||
PRBool aNotSafeToBreak,
|
PRBool aNotSafeToBreak,
|
||||||
|
PRBool aFrameCanContinueTextRun,
|
||||||
nsHTMLReflowMetrics& aMetrics,
|
nsHTMLReflowMetrics& aMetrics,
|
||||||
nsReflowStatus& aStatus);
|
nsReflowStatus& aStatus);
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,18 @@ nsPlaceholderFrame::GetType() const
|
|||||||
return nsLayoutAtoms::placeholderFrame;
|
return nsLayoutAtoms::placeholderFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsPlaceholderFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
||||||
|
{
|
||||||
|
if (!mOutOfFlowFrame) {
|
||||||
|
aContinueTextRun = PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
// first-letter frames can continue text runs, and placeholders for floated
|
||||||
|
// first-letter frames can too
|
||||||
|
return mOutOfFlowFrame->CanContinueTextRun(aContinueTextRun);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void
|
static void
|
||||||
PaintDebugPlaceholder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
PaintDebugPlaceholder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
||||||
|
|||||||
@@ -99,6 +99,8 @@ public:
|
|||||||
virtual PRBool IsEmpty() { return PR_TRUE; }
|
virtual PRBool IsEmpty() { return PR_TRUE; }
|
||||||
virtual PRBool IsSelfEmpty() { return PR_TRUE; }
|
virtual PRBool IsSelfEmpty() { return PR_TRUE; }
|
||||||
|
|
||||||
|
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
||||||
|
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible)
|
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1005,10 +1005,6 @@ nsMathMLContainerFrame::ReflowForeignChild(nsIFrame* aChildFrame,
|
|||||||
const nsHTMLReflowState& aReflowState,
|
const nsHTMLReflowState& aReflowState,
|
||||||
nsReflowStatus& aStatus)
|
nsReflowStatus& aStatus)
|
||||||
{
|
{
|
||||||
// don't bother trying to span words as if they were non-breaking beyond this point
|
|
||||||
if (aReflowState.mLineLayout)
|
|
||||||
aReflowState.mLineLayout->ForgetWordFrames();
|
|
||||||
|
|
||||||
nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState));
|
nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState));
|
||||||
nsresult rv = autoSpaceManager.CreateSpaceManagerFor(aPresContext, this);
|
nsresult rv = autoSpaceManager.CreateSpaceManagerFor(aPresContext, this);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|||||||
@@ -748,6 +748,11 @@ struct nsStyleText : public nsStyleStruct {
|
|||||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_MOZ_PRE_WRAP;
|
mWhiteSpace == NS_STYLE_WHITESPACE_MOZ_PRE_WRAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool WhiteSpaceCanWrap() const {
|
||||||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
|
||||||
|
mWhiteSpace == NS_STYLE_WHITESPACE_MOZ_PRE_WRAP;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nsStyleVisibility : public nsStyleStruct {
|
struct nsStyleVisibility : public nsStyleStruct {
|
||||||
|
|||||||
Reference in New Issue
Block a user