Make nsLineBox.mBounds a LogicalRect. Bug 789096, r=jfkthame

This commit is contained in:
Simon Montagu 2014-04-16 01:03:28 -07:00
Родитель 83c84303ea
Коммит f8a68ec80e
13 изменённых файлов: 263 добавлений и 170 удалений

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

@ -4466,11 +4466,11 @@ nsLayoutUtils::GetFirstLinePosition(const nsIFrame* aFrame,
} else {
// XXX Is this the right test? We have some bogus empty lines
// floating around, but IsEmpty is perhaps too weak.
if (line->GetHeight() != 0 || !line->IsEmpty()) {
nscoord top = line->mBounds.y;
if (line->BSize() != 0 || !line->IsEmpty()) {
nscoord top = line->BStart();
aResult->mTop = top;
aResult->mBaseline = top + line->GetAscent();
aResult->mBottom = top + line->GetHeight();
aResult->mBottom = top + line->BSize();
return true;
}
}
@ -4505,8 +4505,8 @@ nsLayoutUtils::GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
} else {
// XXX Is this the right test? We have some bogus empty lines
// floating around, but IsEmpty is perhaps too weak.
if (line->GetHeight() != 0 || !line->IsEmpty()) {
*aResult = line->mBounds.y + line->GetAscent();
if (line->BSize() != 0 || !line->IsEmpty()) {
*aResult = line->BStart() + line->GetAscent();
return true;
}
}
@ -4531,7 +4531,7 @@ CalculateBlockContentBottom(nsBlockFrame* aFrame)
nsLayoutUtils::CalculateContentBottom(child) + offset);
}
else {
contentBottom = std::max(contentBottom, line->mBounds.YMost());
contentBottom = std::max(contentBottom, line->BEnd());
}
}
return contentBottom;

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

@ -715,8 +715,8 @@ TextOverflow::CreateMarkers(const nsLineBox* aLine,
DisplayListClipState::AutoSaveRestore clipState(mBuilder);
nsRect markerRect = nsRect(aInsideMarkersArea.x - mLeft.mIntrinsicWidth,
aLine->mBounds.y,
mLeft.mIntrinsicWidth, aLine->mBounds.height);
aLine->BStart(),
mLeft.mIntrinsicWidth, aLine->BSize());
markerRect += mBuilder->ToReferenceFrame(mBlock);
ClipMarker(mContentArea + mBuilder->ToReferenceFrame(mBlock),
markerRect, clipState);
@ -730,8 +730,8 @@ TextOverflow::CreateMarkers(const nsLineBox* aLine,
DisplayListClipState::AutoSaveRestore clipState(mBuilder);
nsRect markerRect = nsRect(aInsideMarkersArea.XMost(),
aLine->mBounds.y,
mRight.mIntrinsicWidth, aLine->mBounds.height);
aLine->BStart(),
mRight.mIntrinsicWidth, aLine->BSize());
markerRect += mBuilder->ToReferenceFrame(mBlock);
ClipMarker(mContentArea + mBuilder->ToReferenceFrame(mBlock),
markerRect, clipState);

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

@ -1130,7 +1130,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// the second case can happen.
if (HasOutsideBullet() && !mLines.empty() &&
(mLines.front()->IsBlock() ||
(0 == mLines.front()->mBounds.height &&
(0 == mLines.front()->BSize() &&
mLines.front() != mLines.back() &&
mLines.begin().next()->IsBlock()))) {
// Reflow the bullet
@ -1313,7 +1313,7 @@ nsBlockFrame::CheckForCollapsedBottomMarginFromClearanceLine()
return false;
}
--line;
if (line->mBounds.height != 0 || !line->CachedIsEmpty()) {
if (line->BSize() != 0 || !line->CachedIsEmpty()) {
return false;
}
if (line->HasClearance()) {
@ -1536,7 +1536,7 @@ nsBlockFrame::UpdateOverflow()
for (line_iterator line = begin_lines(), line_end = end_lines();
line != line_end;
++line) {
nsRect bounds = line->mBounds;
nsRect bounds = line->GetPhysicalBounds();
nsOverflowAreas lineAreas(bounds, bounds);
int32_t n = line->GetChildCount();
@ -1649,17 +1649,8 @@ IsAlignedLeft(uint8_t aAlignment,
void
nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
{
const nsStyleText* styleText = StyleText();
const nsStyleTextReset* styleTextReset = StyleTextReset();
// See if we can try and avoid marking all the lines as dirty
bool tryAndSkipLines =
// The block must be LTR (bug 806284)
StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR &&
// The text must be left-aligned.
IsAlignedLeft(styleText->mTextAlign,
aState.mReflowState.mStyleVisibility->mDirection,
styleTextReset->mUnicodeBidi,
this) &&
// The left content-edge must be a constant distance from the left
// border-edge.
!StylePadding()->mPadding.GetLeft().HasPercent();
@ -1672,9 +1663,8 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
if (!tryAndSkipLines) {
IndentBy(stdout, gNoiseIndent);
ListTag(stdout);
printf(": marking all lines dirty: availWidth=%d textAlign=%d\n",
aState.mReflowState.AvailableWidth(),
styleText->mTextAlign);
printf(": marking all lines dirty: availWidth=%d\n",
aState.mReflowState.AvailableWidth());
}
}
#endif
@ -1694,13 +1684,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
}
#endif
// The last line might not be aligned left even if the rest of the block is
bool skipLastLine = NS_STYLE_TEXT_ALIGN_AUTO == styleText->mTextAlignLast ||
IsAlignedLeft(styleText->mTextAlignLast,
aState.mReflowState.mStyleVisibility->mDirection,
styleTextReset->mUnicodeBidi,
this);
for (line_iterator line = begin_lines(), line_end = end_lines();
line != line_end;
++line)
@ -1711,10 +1694,10 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
if (line->IsBlock() ||
line->HasFloats() ||
(!isLastLine && !line->HasBreakAfter()) ||
((isLastLine || !line->IsLineWrapped()) && !skipLastLine) ||
((isLastLine || !line->IsLineWrapped())) ||
line->ResizeReflowOptimizationDisabled() ||
line->IsImpactedByFloat() ||
(line->mBounds.XMost() > newAvailWidth)) {
(line->IEnd() > newAvailWidth)) {
line->MarkDirty();
}
@ -1727,16 +1710,15 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
#ifdef DEBUG
if (gNoisyReflow && !line->IsDirty()) {
IndentBy(stdout, gNoiseIndent + 1);
printf("skipped: line=%p next=%p %s %s%s%s%s breakTypeBefore/After=%d/%d xmost=%d\n",
printf("skipped: line=%p next=%p %s %s%s%s breakTypeBefore/After=%d/%d xmost=%d\n",
static_cast<void*>(line.get()),
static_cast<void*>((line.next() != end_lines() ? line.next().get() : nullptr)),
line->IsBlock() ? "block" : "inline",
line->HasBreakAfter() ? "has-break-after " : "",
line->HasFloats() ? "has-floats " : "",
line->IsImpactedByFloat() ? "impacted " : "",
skipLastLine ? "last-line-left-aligned " : "",
line->GetBreakTypeBefore(), line->GetBreakTypeAfter(),
line->mBounds.XMost());
line->IEnd());
}
#endif
}
@ -1784,8 +1766,8 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
if (floatManager->HasFloatDamage()) {
// Need to check mBounds *and* mCombinedArea to find intersections
// with aLine's floats
nscoord lineYA = aLine->mBounds.y + aDeltaY;
nscoord lineYB = lineYA + aLine->mBounds.height;
nscoord lineYA = aLine->BStart() + aDeltaY;
nscoord lineYB = lineYA + aLine->BSize();
// Scrollable overflow should be sufficient for things that affect
// layout.
nsRect overflow = aLine->GetOverflowArea(eScrollableOverflow);
@ -1809,8 +1791,8 @@ nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
} else {
bool wasImpactedByFloat = aLine->IsImpactedByFloat();
nsFlowAreaRect floatAvailableSpace =
aState.GetFloatAvailableSpaceForHeight(aLine->mBounds.y + aDeltaY,
aLine->mBounds.height,
aState.GetFloatAvailableSpaceForHeight(aLine->BStart() + aDeltaY,
aLine->BSize(),
nullptr);
#ifdef REALLY_NOISY_REFLOW
@ -1865,8 +1847,8 @@ static void DumpLine(const nsBlockReflowState& aState, nsLineBox* aLine,
printf("line=%p mY=%d dirty=%s oldBounds={%d,%d,%d,%d} oldoverflow-vis={%d,%d,%d,%d} oldoverflow-scr={%d,%d,%d,%d} deltaY=%d mPrevBottomMargin=%d childCount=%d\n",
static_cast<void*>(aLine), aState.mY,
aLine->IsDirty() ? "yes" : "no",
aLine->mBounds.x, aLine->mBounds.y,
aLine->mBounds.width, aLine->mBounds.height,
aLine->IStart(), aLine->BStart(),
aLine->ISize(), aLine->BSize(),
ovis.x, ovis.y, ovis.width, ovis.height,
oscr.x, oscr.y, oscr.width, oscr.height,
aDeltaY, aState.mPrevBottomMargin.get(), aLine->GetChildCount());
@ -1973,7 +1955,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// top border-edge of the block frame. If sliding the
// block by deltaY isn't going to put it in the predicted
// position, then we'd better reflow the line.
|| newY != line->mBounds.y + deltaY) {
|| newY != line->BStart() + deltaY) {
line->MarkDirty();
}
} else {
@ -1987,7 +1969,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// We might have to reflow a line that is after a clearing BR.
if (inlineFloatBreakType != NS_STYLE_CLEAR_NONE) {
aState.mY = aState.ClearFloats(aState.mY, inlineFloatBreakType);
if (aState.mY != line->mBounds.y + deltaY) {
if (aState.mY != line->BStart() + deltaY) {
// SlideLine is not going to put the line where the clearance
// put it. Reflow the line to be sure.
line->MarkDirty();
@ -2000,7 +1982,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// If the previous margin is dirty, reflow the current line
line->MarkDirty();
line->ClearPreviousMarginDirty();
} else if (line->mBounds.YMost() + deltaY > aState.mBottomEdge) {
} else if (line->BEnd() + deltaY > aState.mBottomEdge) {
// Lines that aren't dirty but get slid past our height constraint must
// be reflowed.
line->MarkDirty();
@ -2027,6 +2009,27 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
PropagateFloatDamage(aState, line, deltaY);
}
// If the container width has changed reset the container width. If the
// line's writing mode is not ltr, or if the line is not left-aligned, also
// mark the line dirty.
if (aState.mContainerWidth != line->mContainerWidth) {
line->mContainerWidth = aState.mContainerWidth;
bool isLastLine = line == mLines.back() &&
!GetNextInFlow() &&
NS_STYLE_TEXT_ALIGN_AUTO == StyleText()->mTextAlignLast;
uint8_t align = isLastLine ?
StyleText()->mTextAlign : StyleText()->mTextAlignLast;
if (line->mWritingMode.IsVertical() ||
!line->mWritingMode.IsBidiLTR() ||
!IsAlignedLeft(align,
aState.mReflowState.mStyleVisibility->mDirection,
StyleTextReset()->mUnicodeBidi, this)) {
line->MarkDirty();
}
}
if (needToRecoverState && line->IsDirty()) {
// We need to reconstruct the bottom margin only if we didn't
// reflow the previous line and we do need to reflow (or repair
@ -2060,14 +2063,14 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
lastLineMovedUp = true;
bool maybeReflowingForFirstTime =
line->mBounds.x == 0 && line->mBounds.y == 0 &&
line->mBounds.width == 0 && line->mBounds.height == 0;
line->IStart() == 0 && line->BStart() == 0 &&
line->ISize() == 0 && line->BSize() == 0;
// Compute the dirty lines "before" YMost, after factoring in
// Compute the dirty lines "before" BEnd, after factoring in
// the running deltaY value - the running value is implicit in
// aState.mY.
nscoord oldY = line->mBounds.y;
nscoord oldYMost = line->mBounds.YMost();
nscoord oldY = line->BStart();
nscoord oldYMost = line->BEnd();
NS_ASSERTION(!willReflowAgain || !line->IsBlock(),
"Don't reflow blocks while willReflowAgain is true, reflow of block abs-pos children depends on this");
@ -2124,7 +2127,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// it wasn't empty before, any adjacency and clearance changes are irrelevant
// to the result of nextLine->ShouldApplyTopMargin.
if (line.next() != end_lines()) {
bool maybeWasEmpty = oldY == line.next()->mBounds.y;
bool maybeWasEmpty = oldY == line.next()->BStart();
bool isEmpty = line->CachedIsEmpty();
if (maybeReflowingForFirstTime /*1*/ ||
(isEmpty || maybeWasEmpty) /*2/3/4*/) {
@ -2139,7 +2142,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// MarkPreviousMarginDirty on the next line which will force it
// to be reflowed, so this computation of deltaY will not be
// used.
deltaY = line->mBounds.YMost() - oldYMost;
deltaY = line->BEnd() - oldYMost;
// Now do an interrupt check. We want to do this only in the case when we
// actually reflow the line, so that if we get back in here we'll get
@ -2182,7 +2185,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// empty, because that's what PlaceLine does. (Empty blocks may
// want to update mY, e.g. if they have clearance.)
if (line->IsBlock() || !line->CachedIsEmpty()) {
aState.mY = line->mBounds.YMost();
aState.mY = line->BEnd();
}
needToRecoverState = true;
@ -2669,7 +2672,7 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState,
NS_PRECONDITION(aDY != 0, "why slide a line nowhere?");
// Adjust line state
aLine->SlideBy(aDY);
aLine->SlideBy(aDY, aState.mContainerWidth);
// Adjust the frames in the line
nsIFrame* kid = aLine->mFirstChild;
@ -3185,8 +3188,9 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
nsOverflowAreas overflowAreas;
*aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(),
collapsedBottomMargin,
aLine->mBounds, overflowAreas,
frameReflowStatus);
overflowAreas,
frameReflowStatus,
aState.mContainerWidth);
if (!NS_FRAME_IS_FULLY_COMPLETE(frameReflowStatus) &&
ShouldAvoidBreakInside(aState.mReflowState)) {
*aKeepReflowGoing = false;
@ -3205,7 +3209,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// Some of the child block fit
// Advance to new Y position
nscoord newY = aLine->mBounds.YMost();
nscoord newY = aLine->BEnd();
aState.mY = newY;
// Continue the block frame now if it didn't completely fit in
@ -3487,9 +3491,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
#endif
WritingMode wm = GetWritingMode(aLine->mFirstChild);
nscoord lineWidth = aFloatAvailableSpace.mRect.width +
aState.BorderPadding().LeftRight();
LogicalRect lineRect(wm, aFloatAvailableSpace.mRect, lineWidth);
LogicalRect lineRect(wm, aFloatAvailableSpace.mRect, aState.mContainerWidth);
nscoord iStart = lineRect.IStart(wm);
@ -3511,7 +3513,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
availISize, availBSize,
aFloatAvailableSpace.mHasFloats,
false, /*XXX isTopOfPage*/
wm, lineWidth);
wm, aState.mContainerWidth);
aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
@ -4089,7 +4091,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
((aLine == mLines.front() &&
(!aLineLayout.IsZeroBSize() || (aLine == mLines.back()))) ||
(mLines.front() != mLines.back() &&
0 == mLines.front()->mBounds.height &&
0 == mLines.front()->BSize() &&
aLine == mLines.begin().next()))) {
nsHTMLReflowMetrics metrics(aState.mReflowState);
nsIFrame* bullet = GetOutsideBullet();
@ -4109,9 +4111,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsRect oldFloatAvailableSpace(aFloatAvailableSpace);
// As we redo for floats, we can't reduce the amount of height we're
// checking.
aAvailableSpaceHeight = std::max(aAvailableSpaceHeight, aLine->mBounds.height);
aAvailableSpaceHeight = std::max(aAvailableSpaceHeight, aLine->BSize());
aFloatAvailableSpace =
aState.GetFloatAvailableSpaceForHeight(aLine->mBounds.y,
aState.GetFloatAvailableSpaceForHeight(aLine->BStart(),
aAvailableSpaceHeight,
aFloatStateBeforeLine).mRect;
NS_ASSERTION(aFloatAvailableSpace.y == oldFloatAvailableSpace.y, "yikes");
@ -4127,13 +4129,13 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
#ifdef DEBUG
{
static nscoord lastHeight = 0;
if (CRAZY_SIZE(aLine->mBounds.y)) {
lastHeight = aLine->mBounds.y;
if (abs(aLine->mBounds.y - lastHeight) > CRAZY_COORD/10) {
if (CRAZY_SIZE(aLine->BStart())) {
lastHeight = aLine->BStart();
if (abs(aLine->BStart() - lastHeight) > CRAZY_COORD/10) {
nsFrame::ListTag(stdout);
printf(": line=%p y=%d line.bounds.height=%d\n",
static_cast<void*>(aLine.get()),
aLine->mBounds.y, aLine->mBounds.height);
aLine->BStart(), aLine->BSize());
}
}
else {
@ -4161,8 +4163,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
(aLineLayout.GetLineEndsInBR() ||
IsLastLine(aState, aLine)));
aLineLayout.InlineDirAlignFrames(aLine->mBounds, isLastLine,
aLine->GetChildCount());
aLineLayout.InlineDirAlignFrames(aLine, isLastLine);
// From here on, pfd->mBounds rectangles are incorrect because bidi
// might have moved frames around!
@ -4185,7 +4186,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// This line has some height. Therefore the application of the
// previous-bottom-margin should stick.
aState.mPrevBottomMargin.Zero();
newY = aLine->mBounds.YMost();
newY = aLine->BEnd();
}
else {
// Don't let the previous-bottom-margin value affect the newY
@ -4336,7 +4337,7 @@ nsBlockFrame::PushLines(nsBlockReflowState& aState,
{
line->MarkDirty();
line->MarkPreviousMarginDirty();
line->mBounds.SetRect(0, 0, 0, 0);
line->SetBoundsEmpty();
if (line->HasFloats()) {
line->FreeFloats(aState.mFloatCacheFreeList);
}
@ -6117,8 +6118,8 @@ static void DebugOutputDrawLine(int32_t aDepth, nsLineBox* aLine, bool aDrawn) {
printf("%s line=%p bounds=%d,%d,%d,%d ca=%d,%d,%d,%d\n",
aDrawn ? "draw" : "skip",
static_cast<void*>(aLine),
aLine->mBounds.x, aLine->mBounds.y,
aLine->mBounds.width, aLine->mBounds.height,
aLine->IStart(), aLine->BStart(),
aLine->ISize(), aLine->BSize(),
lineArea.x, lineArea.y,
lineArea.width, lineArea.height);
}
@ -6416,7 +6417,7 @@ nsBlockFrame::ChildIsDirty(nsIFrame* aChild)
// height 0 and there is a second line, in which case it lives
// in the second line.
line_iterator bulletLine = begin_lines();
if (bulletLine != end_lines() && bulletLine->mBounds.height == 0 &&
if (bulletLine != end_lines() && bulletLine->BSize() == 0 &&
bulletLine != mLines.back()) {
bulletLine = bulletLine.next();
}

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

@ -245,7 +245,8 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
mY = ty = mSpace.y + mTopMargin.get() + aClearance;
if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + ty - aLine->mBounds.y;
aFrameRS.mBlockDelta =
mOuterReflowState.mBlockDelta + ty - aLine->BStart();
}
// Let frame know that we are reflowing it
@ -310,13 +311,13 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
* margins (CSS2 8.3.1). Also apply relative positioning.
*/
bool
nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
bool aForceFit,
nsLineBox* aLine,
nsCollapsingMargin& aBottomMarginResult,
nsRect& aInFlowBounds,
nsOverflowAreas& aOverflowAreas,
nsReflowStatus aReflowStatus)
nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
bool aForceFit,
nsLineBox* aLine,
nsCollapsingMargin& aBottomMarginResult,
nsOverflowAreas& aOverflowAreas,
nsReflowStatus aReflowStatus,
nscoord aContainerWidth)
{
// Compute collapsed bottom margin value.
if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
@ -386,11 +387,15 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
}
}
aInFlowBounds = nsRect(position.x, position.y - backupContainingBlockAdvance,
mMetrics.Width(), mMetrics.Height());
aLine->SetBounds(aReflowState.GetWritingMode(),
nsRect(position.x,
position.y - backupContainingBlockAdvance,
mMetrics.Width(),
mMetrics.Height()),
aContainerWidth);
aReflowState.ApplyRelativePositioning(&position);
// Now place the frame and complete the reflow process
nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics,
&aReflowState, position.x, position.y, 0);

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

@ -12,7 +12,6 @@
#include "nsIFrame.h"
#include "nsHTMLReflowMetrics.h"
class nsBlockFrame;
class nsBlockReflowState;
struct nsHTMLReflowState;
class nsLineBox;
@ -40,12 +39,12 @@ public:
nsBlockReflowState& aState);
bool PlaceBlock(const nsHTMLReflowState& aReflowState,
bool aForceFit,
nsLineBox* aLine,
nsCollapsingMargin& aBottomMarginResult /* out */,
nsRect& aInFlowBounds,
nsOverflowAreas& aOverflowAreas,
nsReflowStatus aReflowStatus);
bool aForceFit,
nsLineBox* aLine,
nsCollapsingMargin& aBottomMarginResult /* out */,
nsOverflowAreas& aOverflowAreas,
nsReflowStatus aReflowStatus,
nscoord aContainerWidth);
nsCollapsingMargin& GetCarriedOutBottomMargin() {
return mMetrics.mCarriedOutBottomMargin;

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

@ -47,6 +47,8 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
IS_TRUE_OVERFLOW_CONTAINER(aFrame));
const nsMargin& borderPadding = BorderPadding();
mContainerWidth = aReflowState.ComputedWidth() +
aReflowState.ComputedPhysicalBorderPadding().LeftRight();
if (aTopMarginRoot || 0 != aReflowState.ComputedPhysicalBorderPadding().top) {
SetFlag(BRS_ISTOPMARGINROOT, true);

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

@ -188,6 +188,7 @@ public:
// mContentArea.height is not NS_UNCONSTRAINEDSIZE; otherwise
// coordinate overflow may occur.
nsRect mContentArea;
nscoord mContainerWidth;
// Continuation out-of-flow float frames that need to move to our
// next in flow are placed here during reflow. It's a pointer to

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

@ -3451,40 +3451,43 @@ static FrameTarget GetSelectionClosestFrameForLine(
// Account for end of lines (any iterator from the block is valid)
if (aLine == aParent->end_lines())
return DrillDownToSelectionFrame(aParent, true, aFlags);
nsIFrame *closestFromLeft = nullptr, *closestFromRight = nullptr;
nsRect rect = aLine->mBounds;
nscoord closestLeft = rect.x, closestRight = rect.XMost();
nsIFrame *closestFromIStart = nullptr, *closestFromIEnd = nullptr;
nscoord closestIStart = aLine->IStart(), closestIEnd = aLine->IEnd();
WritingMode wm = aLine->mWritingMode;
LogicalPoint pt(wm, aPoint, aLine->mContainerWidth);
for (int32_t n = aLine->GetChildCount(); n;
--n, frame = frame->GetNextSibling()) {
if (!SelfIsSelectable(frame, aFlags) || frame->IsEmpty())
continue;
nsRect frameRect = frame->GetRect();
if (aPoint.x >= frameRect.x) {
if (aPoint.x < frameRect.XMost()) {
LogicalRect frameRect = LogicalRect(wm, frame->GetRect(),
aLine->mContainerWidth);
if (pt.I(wm) >= frameRect.IStart(wm)) {
if (pt.I(wm) < frameRect.IEnd(wm)) {
return GetSelectionClosestFrameForChild(frame, aPoint, aFlags);
}
if (frameRect.XMost() >= closestLeft) {
closestFromLeft = frame;
closestLeft = frameRect.XMost();
if (frameRect.IEnd(wm) >= closestIStart) {
closestFromIStart = frame;
closestIStart = frameRect.IEnd(wm);
}
} else {
if (frameRect.x <= closestRight) {
closestFromRight = frame;
closestRight = frameRect.x;
if (frameRect.IStart(wm) <= closestIEnd) {
closestFromIEnd = frame;
closestIEnd = frameRect.IStart(wm);
}
}
}
if (!closestFromLeft && !closestFromRight) {
if (!closestFromIStart && !closestFromIEnd) {
// We should only get here if there are no selectable frames on a line
// XXX Do we need more elaborate handling here?
return FrameTarget::Null();
}
if (closestFromLeft &&
(!closestFromRight ||
(abs(aPoint.x - closestLeft) <= abs(aPoint.x - closestRight)))) {
return GetSelectionClosestFrameForChild(closestFromLeft, aPoint, aFlags);
if (closestFromIStart &&
(!closestFromIEnd ||
(abs(pt.I(wm) - closestIStart) <= abs(pt.I(wm) - closestIEnd)))) {
return GetSelectionClosestFrameForChild(closestFromIStart, aPoint,
aFlags);
}
return GetSelectionClosestFrameForChild(closestFromRight, aPoint, aFlags);
return GetSelectionClosestFrameForChild(closestFromIEnd, aPoint, aFlags);
}
// This method is for the special handling we do for block frames; they're
@ -3513,15 +3516,18 @@ static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
}
nsBlockFrame::line_iterator curLine = firstLine;
nsBlockFrame::line_iterator closestLine = end;
// Convert aPoint into a LogicalPoint in the writing-mode of this block
WritingMode wm = curLine->mWritingMode;
LogicalPoint pt(wm, aPoint, curLine->mContainerWidth);
while (curLine != end) {
// Check to see if our point lies with the line's Y bounds
nscoord y = aPoint.y - curLine->mBounds.y;
nscoord height = curLine->mBounds.height;
if (y >= 0 && y < height) {
// Check to see if our point lies within the line's block-direction bounds
nscoord BCoord = pt.B(wm) - curLine->BStart();
nscoord BSize = curLine->BSize();
if (BCoord >= 0 && BCoord < BSize) {
closestLine = curLine;
break; // We found the line; stop looking
}
if (y < 0)
if (BCoord < 0)
break;
++curLine;
}
@ -3550,7 +3556,7 @@ static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
return DrillDownToSelectionFrame(aFrame, true, aFlags);
closestLine = prevLine;
} else { // Figure out which line is closer
if (aPoint.y - prevLine->mBounds.YMost() < nextLine->mBounds.y - aPoint.y)
if (pt.B(wm) - prevLine->BEnd() < nextLine->BStart() - pt.B(wm))
closestLine = prevLine;
else
closestLine = nextLine;

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

@ -1186,7 +1186,7 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
// Use the top of the inline box which the placeholder lives in
// as the hypothetical box's top.
aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset;
aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().y + blockYOffset;
} else {
// The element would have been block-level which means it would
// be below the line containing the placeholder frame, unless
@ -1211,11 +1211,11 @@ nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext* aPresContext,
// The top of the hypothetical box is the top of the line
// containing the placeholder, since there is nothing in the
// line before our placeholder except empty frames.
aHypotheticalBox.mTop = lineBox->mBounds.y + blockYOffset;
aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().y + blockYOffset;
} else {
// The top of the hypothetical box is just below the line
// containing the placeholder.
aHypotheticalBox.mTop = lineBox->mBounds.YMost() + blockYOffset;
aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().YMost() + blockYOffset;
}
} else {
// Just use the placeholder's y-offset wrt the containing block

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

@ -14,6 +14,7 @@
#include "nsBidiPresUtils.h"
#endif
#include "nsIFrameInlines.h"
#include "WritingModes.h"
#include "mozilla/Assertions.h"
#include "mozilla/Likely.h"
#include "nsPrintfCString.h"
@ -28,8 +29,13 @@ int32_t nsLineBox::GetCtorCount() { return ctorCount; }
const uint32_t nsLineBox::kMinChildCountForHashtable;
#endif
using namespace mozilla;
nsLineBox::nsLineBox(nsIFrame* aFrame, int32_t aCount, bool aIsBlock)
: mFirstChild(aFrame)
, mContainerWidth(-1)
, mBounds(WritingMode()) // mBounds will be initialized with the correct
// writing mode when it is set
// NOTE: memory is already zeroed since we allocate with AllocateByObjectID.
{
MOZ_COUNT_CTOR(nsLineBox);
@ -75,6 +81,7 @@ NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
{
nsLineBox* newLine = new (aPresShell) nsLineBox(aFrame, aCount, false);
newLine->NoteFramesMovedFrom(aFromLine);
newLine->mContainerWidth = aFromLine->mContainerWidth;
return newLine;
}
@ -241,11 +248,12 @@ nsLineBox::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
if (IsBlock() && !GetCarriedOutBottomMargin().IsZero()) {
str += nsPrintfCString("bm=%d ", GetCarriedOutBottomMargin().get());
}
nsRect bounds = GetPhysicalBounds();
str += nsPrintfCString("{%d,%d,%d,%d} ",
mBounds.x, mBounds.y, mBounds.width, mBounds.height);
bounds.x, bounds.y, bounds.width, bounds.height);
if (mData &&
(!mData->mOverflowAreas.VisualOverflow().IsEqualEdges(mBounds) ||
!mData->mOverflowAreas.ScrollableOverflow().IsEqualEdges(mBounds))) {
(!mData->mOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
!mData->mOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds))) {
str += nsPrintfCString("vis-overflow=%d,%d,%d,%d scr-overflow=%d,%d,%d,%d ",
mData->mOverflowAreas.VisualOverflow().x,
mData->mOverflowAreas.VisualOverflow().y,
@ -440,7 +448,7 @@ nsLineBox::SetCarriedOutBottomMargin(nsCollapsingMargin aValue)
if (IsBlock()) {
if (!aValue.IsZero()) {
if (!mBlockData) {
mBlockData = new ExtraBlockData(mBounds);
mBlockData = new ExtraBlockData(GetPhysicalBounds());
}
changed = aValue != mBlockData->mCarriedOutBottomMargin;
mBlockData->mCarriedOutBottomMargin = aValue;
@ -457,7 +465,8 @@ nsLineBox::SetCarriedOutBottomMargin(nsCollapsingMargin aValue)
void
nsLineBox::MaybeFreeData()
{
if (mData && mData->mOverflowAreas == nsOverflowAreas(mBounds, mBounds)) {
nsRect bounds = GetPhysicalBounds();
if (mData && mData->mOverflowAreas == nsOverflowAreas(bounds, bounds)) {
if (IsInline()) {
if (mInlineData->mFloats.IsEmpty()) {
delete mInlineData;
@ -499,7 +508,7 @@ nsLineBox::AppendFloats(nsFloatCacheFreeList& aFreeList)
if (IsInline()) {
if (aFreeList.NotEmpty()) {
if (!mInlineData) {
mInlineData = new ExtraInlineData(mBounds);
mInlineData = new ExtraInlineData(GetPhysicalBounds());
}
mInlineData->mFloats.Append(aFreeList);
}
@ -533,14 +542,15 @@ nsLineBox::SetOverflowAreas(const nsOverflowAreas& aOverflowAreas)
NS_ASSERTION(aOverflowAreas.Overflow(otype).height >= 0,
"illegal height for combined area");
}
if (!aOverflowAreas.VisualOverflow().IsEqualInterior(mBounds) ||
!aOverflowAreas.ScrollableOverflow().IsEqualEdges(mBounds)) {
nsRect bounds = GetPhysicalBounds();
if (!aOverflowAreas.VisualOverflow().IsEqualInterior(bounds) ||
!aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds)) {
if (!mData) {
if (IsInline()) {
mInlineData = new ExtraInlineData(mBounds);
mInlineData = new ExtraInlineData(bounds);
}
else {
mBlockData = new ExtraBlockData(mBounds);
mBlockData = new ExtraBlockData(bounds);
}
}
mData->mOverflowAreas = aOverflowAreas;
@ -644,7 +654,7 @@ nsLineIterator::GetLine(int32_t aLineNumber,
nsLineBox* line = mLines[aLineNumber];
*aFirstFrameOnLine = line->mFirstChild;
*aNumFramesOnLine = line->GetChildCount();
aLineBounds = line->mBounds;
aLineBounds = line->GetPhysicalBounds();
uint32_t flags = 0;
if (line->IsBlock()) {
@ -727,7 +737,7 @@ nsLineIterator::FindFrameAt(int32_t aLineNumber,
return NS_OK;
}
if (line->mBounds.width == 0 && line->mBounds.height == 0)
if (line->ISize() == 0 && line->BSize() == 0)
return NS_ERROR_FAILURE;
nsIFrame* frame = line->mFirstChild;

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

@ -447,28 +447,46 @@ public:
// layout (except for handling of 'overflow').
void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
nsRect GetOverflowArea(nsOverflowType aType) {
return mData ? mData->mOverflowAreas.Overflow(aType) : mBounds;
return mData ? mData->mOverflowAreas.Overflow(aType) : GetPhysicalBounds();
}
nsOverflowAreas GetOverflowAreas() {
if (mData) {
return mData->mOverflowAreas;
}
return nsOverflowAreas(mBounds, mBounds);
nsRect bounds = GetPhysicalBounds();
return nsOverflowAreas(bounds, bounds);
}
nsRect GetVisualOverflowArea()
{ return GetOverflowArea(eVisualOverflow); }
nsRect GetScrollableOverflowArea()
{ return GetOverflowArea(eScrollableOverflow); }
void SlideBy(nscoord aDY) {
mBounds.y += aDY;
void SlideBy(nscoord aDBCoord, nscoord aContainerWidth) {
NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
"container width doesn't match");
mContainerWidth = aContainerWidth;
mBounds.BStart(mWritingMode) += aDBCoord;
if (mData) {
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
mData->mOverflowAreas.Overflow(otype).y += aDY;
mData->mOverflowAreas.Overflow(otype).y += aDBCoord;
}
}
}
void IndentBy(nscoord aDICoord, nscoord aContainerWidth) {
NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
"container width doesn't match");
mContainerWidth = aContainerWidth;
mBounds.IStart(mWritingMode) += aDICoord;
}
void ExpandBy(nscoord aDISize, nscoord aContainerWidth) {
NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
"container width doesn't match");
mContainerWidth = aContainerWidth;
mBounds.ISize(mWritingMode) += aDISize;
}
/**
* The ascent (distance from top to baseline) of the linebox is the
* ascent of the anonymous inline box (for which we don't actually
@ -480,8 +498,29 @@ public:
nscoord GetAscent() const { return mAscent; }
void SetAscent(nscoord aAscent) { mAscent = aAscent; }
nscoord GetHeight() const {
return mBounds.height;
nscoord BStart() const {
return mBounds.BStart(mWritingMode);
}
nscoord BSize() const {
return mBounds.BSize(mWritingMode);
}
nscoord BEnd() const {
return mBounds.BEnd(mWritingMode);
}
nscoord IStart() const {
return mBounds.IStart(mWritingMode);
}
nscoord ISize() const {
return mBounds.ISize(mWritingMode);
}
nscoord IEnd() const {
return mBounds.IEnd(mWritingMode);
}
void SetBoundsEmpty() {
mBounds.IStart(mWritingMode) = 0;
mBounds.ISize(mWritingMode) = 0;
mBounds.BStart(mWritingMode) = 0;
mBounds.BSize(mWritingMode) = 0;
}
static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
@ -539,7 +578,38 @@ public:
nsIFrame* mFirstChild;
nsRect mBounds;
mozilla::WritingMode mWritingMode;
nscoord mContainerWidth;
private:
mozilla::LogicalRect mBounds;
public:
const mozilla::LogicalRect& GetBounds() { return mBounds; }
nsRect GetPhysicalBounds() const
{
if (mBounds.IsEmpty()) {
return nsRect(0, 0, 0, 0);
}
NS_ASSERTION(mContainerWidth != -1, "mContainerWidth not initialized");
return mBounds.GetPhysicalRect(mWritingMode, mContainerWidth);
}
void SetBounds(mozilla::WritingMode aWritingMode,
nscoord aIStart, nscoord aBStart,
nscoord aISize, nscoord aBSize,
nscoord aContainerWidth)
{
mWritingMode = aWritingMode;
mContainerWidth = aContainerWidth;
mBounds = mozilla::LogicalRect(aWritingMode, aIStart, aBStart,
aISize, aBSize);
}
void SetBounds(mozilla::WritingMode aWritingMode,
nsRect aRect, nscoord aContainerWidth)
{
mWritingMode = aWritingMode;
mContainerWidth = aContainerWidth;
mBounds = mozilla::LogicalRect(aWritingMode, aRect, aContainerWidth);
}
// mFlags.mHasHashedFrames says which one to use
union {

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

@ -1481,18 +1481,18 @@ nsLineLayout::BlockDirAlignLine()
}
// Fill in returned line-box and max-element-width data
mLineBox->mBounds.x = psd->mIStart;
mLineBox->mBounds.y = mBStartEdge;
mLineBox->mBounds.width = psd->mICoord - psd->mIStart;
mLineBox->mBounds.height = lineBSize;
mLineBox->SetBounds(lineWM,
psd->mIStart, mBStartEdge,
psd->mICoord - psd->mIStart, lineBSize,
mContainerWidth);
mFinalLineBSize = lineBSize;
mLineBox->SetAscent(baselineBCoord - mBStartEdge);
#ifdef NOISY_BLOCKDIR_ALIGN
printf(
" [line]==> bounds{x,y,w,h}={%d,%d,%d,%d} lh=%d a=%d\n",
mLineBox->mBounds.x, mLineBox->mBounds.y,
mLineBox->mBounds.width, mLineBox->mBounds.height,
mLineBox->mBounds.IStart(lineWM), mLineBox->mBounds.BStart(lineWM),
mLineBox->mBounds.ISize(lineWM), mLineBox->mBounds.BSize(lineWM),
mFinalLineBSize, mLineBox->GetAscent());
#endif
@ -2509,29 +2509,27 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState
}
void
nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds,
bool aIsLastLine,
int32_t aFrameCount)
nsLineLayout::InlineDirAlignFrames(nsLineBox* aLine,
bool aIsLastLine)
{
/**
* NOTE: aIsLastLine ain't necessarily so: it is correctly set by caller
* only in cases where the last line needs special handling.
*/
PerSpanData* psd = mRootSpan;
WritingMode lineWM = psd->mWritingMode;
NS_WARN_IF_FALSE(psd->mIEnd != NS_UNCONSTRAINEDSIZE,
"have unconstrained width; this should only result from "
"very large sizes, not attempts at intrinsic width "
"calculation");
nscoord availWidth = psd->mIEnd - psd->mIStart;
nscoord remainingWidth = availWidth - aLineBounds.width;
nscoord availISize = psd->mIEnd - psd->mIStart;
nscoord remainingISize = availISize - aLine->ISize();
#ifdef NOISY_INLINEDIR_ALIGN
nsFrame::ListTag(stdout, mBlockReflowState->frame);
printf(": availWidth=%d lineBounds.x=%d lineWidth=%d delta=%d\n",
availWidth, aLineBounds.x, aLineBounds.width, remainingWidth);
printf(": availISize=%d lineBounds.IStart=%d lineISize=%d delta=%d\n",
availISize, aLine->IStart(), aLine->ISize(), remainingISize);
#endif
WritingMode lineWM = psd->mWritingMode;
// 'text-align-last: auto' is equivalent to the value of the 'text-align'
// property except when 'text-align' is set to 'justify', in which case it
// is 'justify' when 'text-justify' is 'distribute' and 'start' otherwise.
@ -2552,24 +2550,25 @@ nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds,
}
}
if ((remainingWidth > 0 || textAlignTrue) &&
if ((remainingISize > 0 || textAlignTrue) &&
!(mBlockReflowState->frame->IsSVGText())) {
switch (textAlign) {
case NS_STYLE_TEXT_ALIGN_JUSTIFY:
int32_t numSpaces;
int32_t numLetters;
ComputeJustificationWeights(psd, &numSpaces, &numLetters);
if (numSpaces > 0) {
FrameJustificationState state =
{ numSpaces, numLetters, remainingWidth, 0, 0, 0, 0, 0 };
{ numSpaces, numLetters, remainingISize, 0, 0, 0, 0, 0 };
// Apply the justification, and make sure to update our linebox
// width to account for it.
aLineBounds.width += ApplyFrameJustification(psd, &state);
remainingWidth = availWidth - aLineBounds.width;
aLine->ExpandBy(ApplyFrameJustification(psd, &state),
mContainerWidth);
remainingISize = availISize - aLine->ISize();
break;
}
// Fall through to the default case if we could not justify to fill
@ -2582,25 +2581,25 @@ nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds,
case NS_STYLE_TEXT_ALIGN_LEFT:
case NS_STYLE_TEXT_ALIGN_MOZ_LEFT:
if (!lineWM.IsBidiLTR()) {
dx = remainingWidth;
dx = remainingISize;
}
break;
case NS_STYLE_TEXT_ALIGN_RIGHT:
case NS_STYLE_TEXT_ALIGN_MOZ_RIGHT:
if (lineWM.IsBidiLTR()) {
dx = remainingWidth;
dx = remainingISize;
}
break;
case NS_STYLE_TEXT_ALIGN_END:
dx = remainingWidth;
dx = remainingISize;
break;
case NS_STYLE_TEXT_ALIGN_CENTER:
case NS_STYLE_TEXT_ALIGN_MOZ_CENTER:
dx = remainingWidth / 2;
dx = remainingISize / 2;
break;
}
}
@ -2610,12 +2609,13 @@ nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds,
pfd->mBounds.IStart(lineWM) += dx;
pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth);
}
aLineBounds.x += dx;
aLine->IndentBy(dx, mContainerWidth);
}
if (mPresContext->BidiEnabled() &&
(!mPresContext->IsVisualMode() || !lineWM.IsBidiLTR())) {
nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame, aFrameCount,
nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame,
aLine->GetChildCount(),
lineWM, mContainerWidth);
}
}

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

@ -94,8 +94,7 @@ public:
bool TrimTrailingWhiteSpace();
void InlineDirAlignFrames(nsRect& aLineBounds, bool aIsLastLine,
int32_t aFrameCount);
void InlineDirAlignFrames(nsLineBox* aLine, bool aIsLastLine);
/**
* Handle all the relative positioning in the line, compute the