From b99f5df532991b57afad3bd184ee388ed61b15e2 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Tue, 11 Mar 2014 09:22:52 +0100 Subject: [PATCH] Backed out changeset aeff4052ef00 (bug 789096) --- layout/base/nsBidiPresUtils.cpp | 182 ++-- layout/base/nsBidiPresUtils.h | 46 +- layout/generic/WritingModes.h | 17 - layout/generic/nsBlockFrame.cpp | 58 +- layout/generic/nsBlockReflowContext.cpp | 2 +- layout/generic/nsContainerFrame.h | 7 +- layout/generic/nsFirstLetterFrame.cpp | 17 +- layout/generic/nsFrame.cpp | 14 - layout/generic/nsIFrame.h | 9 - layout/generic/nsInlineFrame.cpp | 30 +- layout/generic/nsLineLayout.cpp | 1132 +++++++++++------------ layout/generic/nsLineLayout.h | 90 +- layout/generic/nsTextFrame.cpp | 2 +- 13 files changed, 763 insertions(+), 843 deletions(-) diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index cf25736faf61..f30b0c263693 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -1228,10 +1228,8 @@ nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame, } void -nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, - int32_t aNumFramesOnLine, - WritingMode aLineWM, - nscoord& aLineWidth) +nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, + int32_t aNumFramesOnLine) { // If this line consists of a line frame, reorder the line frame's children. if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) { @@ -1244,7 +1242,7 @@ nsBidiPresUtils::ReorderFrames(nsIFrame* aFirstFrameOnLine, } BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine); - RepositionInlineFrames(&bld, aFirstFrameOnLine, aLineWM, aLineWidth); + RepositionInlineFrames(&bld, aFirstFrameOnLine); } nsIFrame* @@ -1284,20 +1282,22 @@ nsBidiPresUtils::GetFrameBaseLevel(nsIFrame* aFrame) } void -nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame, - nsContinuationStates* aContinuationStates, - bool& aIsFirst /* out */, - bool& aIsLast /* out */) +nsBidiPresUtils::IsLeftOrRightMost(nsIFrame* aFrame, + nsContinuationStates* aContinuationStates, + bool& aIsLeftMost /* out */, + bool& aIsRightMost /* out */) { + const nsStyleVisibility* vis = aFrame->StyleVisibility(); + bool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); + /* - * Since we lay out frames in the line's direction, visiting a frame with - * 'mFirstVisualFrame == nullptr', means it's the first appearance of one - * of its continuation chain frames on the line. - * To determine if it's the last visual frame of its continuation chain on - * the line or not, we count the number of frames of the chain on the line, - * and then reduce it when we lay out a frame of the chain. If this value - * becomes 1 it means that it's the last visual frame of its continuation - * chain on this line. + * Since we lay out frames from left to right (in both LTR and RTL), visiting a + * frame with 'mFirstVisualFrame == nullptr', means it's the first appearance of + * one of its continuation chain frames on the line. + * To determine if it's the last visual frame of its continuation chain on the line + * or not, we count the number of frames of the chain on the line, and then reduce + * it when we lay out a frame of the chain. If this value becomes 1 it means + * that it's the last visual frame of its continuation chain on this line. */ nsFrameContinuationState* frameState = aContinuationStates->GetEntry(aFrame); @@ -1334,18 +1334,20 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame, } frameState->mHasContOnNextLines = (frame != nullptr); - aIsFirst = !frameState->mHasContOnPrevLines; + aIsLeftMost = isLTR ? !frameState->mHasContOnPrevLines + : !frameState->mHasContOnNextLines; firstFrameState = frameState; } else { // aFrame is not the first visual frame of its continuation chain - aIsFirst = false; + aIsLeftMost = false; firstFrameState = aContinuationStates->GetEntry(frameState->mFirstVisualFrame); } - aIsLast = (firstFrameState->mFrameCount == 1 && - !firstFrameState->mHasContOnNextLines); + aIsRightMost = (firstFrameState->mFrameCount == 1) && + (isLTR ? !firstFrameState->mHasContOnNextLines + : !firstFrameState->mHasContOnPrevLines); - if ((aIsFirst || aIsLast) && + if ((aIsLeftMost || aIsRightMost) && (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT)) { // For ib splits, don't treat anything except the last part as // endmost or anything except the first part as startmost. @@ -1353,11 +1355,19 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame, nsIFrame* firstContinuation = aFrame->FirstContinuation(); if (firstContinuation->FrameIsNonLastInIBSplit()) { // We are not endmost - aIsLast = false; + if (isLTR) { + aIsRightMost = false; + } else { + aIsLeftMost = false; + } } if (firstContinuation->FrameIsNonFirstInIBSplit()) { // We are not startmost - aIsFirst = false; + if (isLTR) { + aIsLeftMost = false; + } else { + aIsRightMost = false; + } } } @@ -1366,39 +1376,29 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame* aFrame, } void -nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, - bool aIsEvenLevel, - nscoord& aStart, - nsContinuationStates* aContinuationStates, - WritingMode aLineWM, - nscoord& aLineWidth) +nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, + bool aIsOddLevel, + nscoord& aLeft, + nsContinuationStates* aContinuationStates) { if (!aFrame) return; - bool isFirst, isLast; - IsFirstOrLast(aFrame, - aContinuationStates, - isFirst /* out */, - isLast /* out */); + bool isLeftMost, isRightMost; + IsLeftOrRightMost(aFrame, + aContinuationStates, + isLeftMost /* out */, + isRightMost /* out */); - WritingMode frameWM = aFrame->GetWritingMode(); nsInlineFrame* testFrame = do_QueryFrame(aFrame); - - //XXX temporary until GetSkipSides is logicalized - bool isLeftMost = false, isRightMost = false; if (testFrame) { aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET); - isLeftMost = ((isFirst && frameWM.IsBidiLTR()) || - (isLast && !frameWM.IsBidiLTR())); if (isLeftMost) aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LEFT_MOST); else aFrame->RemoveStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LEFT_MOST); - isRightMost = ((isLast && frameWM.IsBidiLTR()) || - (isFirst && !frameWM.IsBidiLTR())); if (isRightMost) aFrame->AddStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_RIGHT_MOST); else @@ -1407,30 +1407,26 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, // This method is called from nsBlockFrame::PlaceLine via the call to // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines // have been reflowed, which is required for GetUsedMargin/Border/Padding - LogicalMargin margin(frameWM, aFrame->GetUsedMargin()); - if (isFirst) { - aStart += margin.IStart(frameWM); - } + nsMargin margin = aFrame->GetUsedMargin(); + if (isLeftMost) + aLeft += margin.left; - nscoord start = aStart; - nscoord frameWidth = aFrame->GetSize().width; + nscoord start = aLeft; if (!IsBidiLeaf(aFrame)) { - nscoord iCoord = 0; - LogicalMargin borderPadding(frameWM, aFrame->GetUsedBorderAndPadding()); - if (isFirst) { - iCoord += borderPadding.IStart(frameWM); + nscoord x = 0; + nsMargin borderPadding = aFrame->GetUsedBorderAndPadding(); + if (isLeftMost) { + x += borderPadding.left; } - // If the resolved direction of the container is different from the - // direction of the frame, we need to traverse the child list in reverse - // order, to make it O(n) we store the list locally and iterate the list - // in reverse - bool reverseOrder = aIsEvenLevel != frameWM.IsBidiLTR(); + // If aIsOddLevel is true, so we need to traverse the child list + // in reverse order, to make it O(n) we store the list locally and + // iterate the list reversely nsTArray childList; nsIFrame *frame = aFrame->GetFirstPrincipalChild(); - if (frame && reverseOrder) { + if (frame && aIsOddLevel) { childList.AppendElement((nsIFrame*)nullptr); while (frame) { childList.AppendElement(frame); @@ -1443,33 +1439,27 @@ nsBidiPresUtils::RepositionFrame(nsIFrame* aFrame, int32_t index = 0; while (frame) { RepositionFrame(frame, - aIsEvenLevel, - iCoord, - aContinuationStates, - frameWM, - frameWidth); + aIsOddLevel, + x, + aContinuationStates); index++; - frame = reverseOrder ? + frame = aIsOddLevel ? childList[childList.Length() - index - 1] : frame->GetNextSibling(); } - if (isLast) { - iCoord += borderPadding.IEnd(frameWM); + if (isRightMost) { + x += borderPadding.right; } - aStart += iCoord; + aLeft += x; } else { - aStart += frameWidth; + aLeft += aFrame->GetSize().width; } + nsRect rect = aFrame->GetRect(); + aFrame->SetRect(nsRect(start, rect.y, aLeft - start, rect.height)); - LogicalRect logicalRect(aLineWM, aFrame->GetRect(), aLineWidth); - logicalRect.IStart(aLineWM) = start; - logicalRect.ISize(aLineWM) = aStart - start; - aFrame->SetRect(aLineWM, logicalRect, aLineWidth); - - if (isLast) { - aStart += margin.IEnd(frameWM); - } + if (isRightMost) + aLeft += margin.right; } void @@ -1494,23 +1484,21 @@ nsBidiPresUtils::InitContinuationStates(nsIFrame* aFrame, void nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld, - nsIFrame* aFirstChild, - WritingMode aLineWM, - nscoord& aLineWidth) + nsIFrame* aFirstChild) { - nscoord startSpace = 0; + const nsStyleVisibility* vis = aFirstChild->StyleVisibility(); + bool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection); + nscoord leftSpace = 0; // This method is called from nsBlockFrame::PlaceLine via the call to // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines // have been reflowed, which is required for GetUsedMargin/Border/Padding - WritingMode frameWM = aFirstChild->GetWritingMode(); - LogicalMargin margin(frameWM, aFirstChild->GetUsedMargin()); + nsMargin margin = aFirstChild->GetUsedMargin(); if (!aFirstChild->GetPrevContinuation() && !aFirstChild->FrameIsNonFirstInIBSplit()) - startSpace = margin.IStart(frameWM); + leftSpace = isLTR ? margin.left : margin.right; - nscoord start = LogicalRect(aLineWM, aFirstChild->GetRect(), - aLineWidth).IStart(aLineWM) - startSpace; + nscoord left = aFirstChild->GetPosition().x - leftSpace; nsIFrame* frame; int32_t count = aBld->mVisualFrames.Length(); int32_t index; @@ -1523,25 +1511,13 @@ nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld, } // Reposition frames in visual order - int32_t step, limit; - if (aLineWM.IsBidiLTR()) { - index = 0; - step = 1; - limit = count; - } else { - index = count - 1; - step = -1; - limit = -1; - } - for (; index != limit; index += step) { + for (index = 0; index < count; index++) { frame = aBld->VisualFrameAt(index); RepositionFrame(frame, - !(aBld->mLevels[aBld->mIndexMap[index]] & 1), - start, - &continuationStates, - aLineWM, - aLineWidth); - } + (aBld->mLevels[aBld->mIndexMap[index]] & 1), + left, + &continuationStates); + } // for } bool diff --git a/layout/base/nsBidiPresUtils.h b/layout/base/nsBidiPresUtils.h index d163f5941341..39965adaa6a1 100644 --- a/layout/base/nsBidiPresUtils.h +++ b/layout/base/nsBidiPresUtils.h @@ -27,7 +27,6 @@ class nsRenderingContext; class nsBlockInFlowLineIterator; class nsStyleContext; template class nsTHashtable; -namespace mozilla { class WritingMode; } /** * A structure representing some continuation state for each frame on the line, @@ -160,9 +159,7 @@ public: * @lina 05/02/2000 */ static void ReorderFrames(nsIFrame* aFirstFrameOnLine, - int32_t aNumFramesOnLine, - mozilla::WritingMode aLineWM, - nscoord& aLineWidth); + int32_t aNumFramesOnLine); /** * Format Unicode text, taking into account bidi capabilities @@ -380,27 +377,24 @@ private: nsBlockInFlowLineIterator* aLineIter, nsIFrame* aCurrentFrame, BidiParagraphData* aBpd); - + /* - * Position aFrame and its descendants to their visual places. Also if aFrame - * is not leaf, resize it to embrace its children. + * Position aFrame and it's descendants to their visual places. Also if aFrame + * is not leaf, resize it to embrace it's children. * - * @param aFrame The frame which itself and its children are - * going to be repositioned - * @param aIsEvenLevel TRUE means the embedding level of this frame - * is even (LTR) - * @param[in,out] aStart IN value is the starting position of aFrame - * (without considering its inline-start margin) - * OUT value will be the ending position of aFrame - * (after adding its inline-end margin) + * @param aFrame The frame which itself and its children are going + * to be repositioned + * @param aIsOddLevel TRUE means the embedding level of this frame is odd + * @param[in,out] aLeft IN value is the starting position of aFrame(without + * considering its left margin) + * OUT value will be the ending position of aFrame(after + * adding its right margin) * @param aContinuationStates A map from nsIFrame* to nsFrameContinuationState */ static void RepositionFrame(nsIFrame* aFrame, - bool aIsEvenLevel, - nscoord& aStart, - nsContinuationStates* aContinuationStates, - mozilla::WritingMode aLineWM, - nscoord& aLineWidth); + bool aIsOddLevel, + nscoord& aLeft, + nsContinuationStates* aContinuationStates); /* * Initialize the continuation state(nsFrameContinuationState) to @@ -428,10 +422,10 @@ private: * @param[out] aIsLeftMost TRUE means aFrame is leftmost frame or continuation * @param[out] aIsRightMost TRUE means aFrame is rightmost frame or continuation */ - static void IsFirstOrLast(nsIFrame* aFrame, - nsContinuationStates* aContinuationStates, - bool& aIsFirst /* out */, - bool& aIsLast /* out */); + static void IsLeftOrRightMost(nsIFrame* aFrame, + nsContinuationStates* aContinuationStates, + bool& aIsLeftMost /* out */, + bool& aIsRightMost /* out */); /** * Adjust frame positions following their visual order @@ -441,9 +435,7 @@ private: * @lina 04/11/2000 */ static void RepositionInlineFrames(BidiLineData* aBld, - nsIFrame* aFirstChild, - mozilla::WritingMode aLineWM, - nscoord& aLineWidth); + nsIFrame* aFirstChild); /** * Helper method for Resolve() diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h index 46bc4b83530c..082ae4177da6 100644 --- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -833,12 +833,6 @@ public: *this : LogicalMargin(aToMode, GetPhysicalMargin(aFromMode)); } - bool IsEmpty() const - { - return (mMargin.left == 0 && mMargin.top == 0 && - mMargin.right == 0 && mMargin.bottom == 0); - } - private: friend class LogicalRect; @@ -1129,17 +1123,6 @@ public: return aWritingMode.IsVertical() ? mRect.XMost() : mRect.YMost(); } - bool IsEmpty() const - { - return (mRect.x == 0 && mRect.y == 0 && - mRect.width == 0 && mRect.height == 0); - } - - bool IsZeroSize() const - { - return (mRect.width == 0 && mRect.height == 0); - } - /* XXX are these correct? nscoord ILeft(WritingMode aWritingMode) const { diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 0e295d5bd4b3..8a4d34eef443 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1450,7 +1450,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, *aBottomEdgeOfChildren = bottomEdgeOfChildren; #ifdef DEBUG_blocks - if (CRAZY_SIZE(aMetrics.Width()) || CRAZY_SIZE(aMetrics.Height())) { + if (CRAZY_WIDTH(aMetrics.Width()) || CRAZY_HEIGHT(aMetrics.Height())) { ListTag(stdout); printf(": WARNING: desired:%d,%d\n", aMetrics.Width(), aMetrics.Height()); } @@ -3448,32 +3448,35 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, this, aFloatAvailableSpace.mHasFloats); #endif - WritingMode wm = GetWritingMode(aLine->mFirstChild); - nscoord lineWidth = aFloatAvailableSpace.mRect.width + - aState.BorderPadding().LeftRight(); - LogicalRect lineRect(wm, aFloatAvailableSpace.mRect, lineWidth); - - nscoord iStart = lineRect.IStart(wm); - - nscoord availISize = lineRect.ISize(wm); - nscoord availBSize; + nscoord x = aFloatAvailableSpace.mRect.x; + nscoord availWidth = aFloatAvailableSpace.mRect.width; + nscoord availHeight; if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) { - availBSize = NS_UNCONSTRAINEDSIZE; + availHeight = NS_UNCONSTRAINEDSIZE; } else { /* XXX get the height right! */ - availBSize = lineRect.BSize(wm); + availHeight = aFloatAvailableSpace.mRect.height; } // Make sure to enable resize optimization before we call BeginLineReflow // because it might get disabled there aLine->EnableResizeReflowOptimization(); - aLineLayout.BeginLineReflow(iStart, aState.mY, - availISize, availBSize, + // For unicode-bidi: plaintext, we need to get the direction of the line from + // the resolved paragraph level of the first frame on the line, not the block + // frame, because the block frame could be split by hard line breaks into + // multiple paragraphs with different base direction + uint8_t direction = + (StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT) ? + nsBidiPresUtils::GetFrameBaseLevel(aLine->mFirstChild) & 1 : + StyleVisibility()->mDirection; + + aLineLayout.BeginLineReflow(x, aState.mY, + availWidth, availHeight, aFloatAvailableSpace.mHasFloats, false, /*XXX isTopOfPage*/ - wm, lineWidth); + direction); aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, false); @@ -4049,7 +4052,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, bool addedBullet = false; if (HasOutsideBullet() && ((aLine == mLines.front() && - (!aLineLayout.IsZeroBSize() || (aLine == mLines.back()))) || + (!aLineLayout.IsZeroHeight() || (aLine == mLines.back()))) || (mLines.front() != mLines.back() && 0 == mLines.front()->mBounds.height && aLine == mLines.begin().next()))) { @@ -4061,7 +4064,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, aLineLayout.AddBulletFrame(bullet, metrics); addedBullet = true; } - aLineLayout.BlockDirAlignLine(); + aLineLayout.VerticalAlignLine(); // We want to compare to the available space that we would have had in // the line's height *before* we placed any floats in the line itself. @@ -4089,9 +4092,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, #ifdef DEBUG { static nscoord lastHeight = 0; - if (CRAZY_SIZE(aLine->mBounds.y)) { + if (CRAZY_HEIGHT(aLine->mBounds.y)) { lastHeight = aLine->mBounds.y; - if (abs(aLine->mBounds.y - lastHeight) > CRAZY_COORD/10) { + if (abs(aLine->mBounds.y - lastHeight) > CRAZY_H/10) { nsFrame::ListTag(stdout); printf(": line=%p y=%d line.bounds.height=%d\n", static_cast(aLine.get()), @@ -4122,9 +4125,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign) && (aLineLayout.GetLineEndsInBR() || IsLastLine(aState, aLine))); - - aLineLayout.InlineDirAlignFrames(aLine->mBounds, isLastLine, - aLine->GetChildCount()); + aLineLayout.HorizontalAlignFrames(aLine->mBounds, isLastLine); + // XXX: not only bidi: right alignment can be broken after + // RelativePositionFrames!!! + // XXXldb Is something here considering relatively positioned frames at + // other than their original positions? +#ifdef IBMBIDI + // XXXldb Why don't we do this earlier? + if (aState.mPresContext->BidiEnabled()) { + if (!aState.mPresContext->IsVisualMode() || + StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { + nsBidiPresUtils::ReorderFrames(aLine->mFirstChild, aLine->GetChildCount()); + } // not visual mode + } // bidi enabled +#endif // IBMBIDI // From here on, pfd->mBounds rectangles are incorrect because bidi // might have moved frames around! diff --git a/layout/generic/nsBlockReflowContext.cpp b/layout/generic/nsBlockReflowContext.cpp index 341056b6706c..dcc8770d2bde 100644 --- a/layout/generic/nsBlockReflowContext.cpp +++ b/layout/generic/nsBlockReflowContext.cpp @@ -262,7 +262,7 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace, #ifdef DEBUG if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) { - if (CRAZY_SIZE(mMetrics.Width()) || CRAZY_SIZE(mMetrics.Height())) { + if (CRAZY_WIDTH(mMetrics.Width()) || CRAZY_HEIGHT(mMetrics.Height())) { printf("nsBlockReflowContext: "); nsFrame::ListTag(stdout, mFrame); printf(" metrics=%d,%d!\n", mMetrics.Width(), mMetrics.Height()); diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index 7b37d887dff9..5641f3d66f91 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -34,8 +34,11 @@ class FramePropertyTable; // dependency on nsDeviceContext.h. It doesn't matter if it's a // little off. #ifdef DEBUG -#define CRAZY_COORD (1000000*60) -#define CRAZY_SIZE(_x) (((_x) < -CRAZY_COORD) || ((_x) > CRAZY_COORD)) +#define CRAZY_W (1000000*60) +#define CRAZY_H CRAZY_W + +#define CRAZY_WIDTH(_x) (((_x) < -CRAZY_W) || ((_x) > CRAZY_W)) +#define CRAZY_HEIGHT(_y) (((_y) < -CRAZY_H) || ((_y) > CRAZY_H)) #endif /** diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index a215ea473f1e..d3dcda12b9be 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -188,10 +188,21 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowState rs(aPresContext, aReflowState, kid, availSize); nsLineLayout ll(aPresContext, nullptr, &aReflowState, nullptr); + // For unicode-bidi: plaintext, we need to get the direction of the line + // from the resolved paragraph level of the child, not the block frame, + // because the block frame could be split by hard line breaks into + // multiple paragraphs with different base direction + uint8_t direction; + nsIFrame* containerFrame = ll.LineContainerFrame(); + if (containerFrame->StyleTextReset()->mUnicodeBidi & + NS_STYLE_UNICODE_BIDI_PLAINTEXT) { + FramePropertyTable *propTable = aPresContext->PropertyTable(); + direction = NS_PTR_TO_INT32(propTable->Get(kid, BaseLevelProperty())) & 1; + } else { + direction = containerFrame->StyleVisibility()->mDirection; + } ll.BeginLineReflow(bp.left, bp.top, availSize.width, NS_UNCONSTRAINEDSIZE, - false, true, - ll.LineContainerFrame()->GetWritingMode(kid), - aReflowState.AvailableWidth()); + false, true, direction); rs.mLineLayout = ≪ ll.SetInFirstLetter(true); ll.SetFirstLetterStyleOK(true); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 6d85ce38ac67..11fd4ae655eb 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -975,20 +975,6 @@ nsIFrame::GetPaddingRect() const return GetPaddingRectRelativeToSelf() + GetPosition(); } -WritingMode -nsIFrame::GetWritingMode(nsIFrame* aSubFrame) const -{ - WritingMode writingMode = GetWritingMode(); - - if (!writingMode.IsVertical() && - (StyleTextReset()->mUnicodeBidi & NS_STYLE_UNICODE_BIDI_PLAINTEXT)) { - nsBidiLevel frameLevel = nsBidiPresUtils::GetFrameBaseLevel(aSubFrame); - writingMode.SetDirectionFromBidiLevel(frameLevel); - } - - return writingMode; -} - nsRect nsIFrame::GetMarginRectRelativeToSelf() const { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index a6a4ac48b171..51c066431c7d 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -672,15 +672,6 @@ public: return mozilla::WritingMode(StyleVisibility()); } - /** - * Get the writing mode of this frame, but if it is styled with - * unicode-bidi: plaintext, reset the direction to the resolved paragraph - * level of the given subframe (typically the first frame on the line), - * not this frame's writing mode, because the container frame could be split - * by hard line breaks into multiple paragraphs with different base direction. - */ - mozilla::WritingMode GetWritingMode(nsIFrame* aSubFrame) const; - /** * Bounding rect of the frame. The values are in app units, and the origin is * relative to the upper-left of the geometric parent. The size includes the diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 386da5908b14..87faec3a58c1 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -487,21 +487,23 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, nsLineLayout* lineLayout = aReflowState.mLineLayout; bool inFirstLine = aReflowState.mLineLayout->GetInFirstLine(); RestyleManager* restyleManager = aPresContext->RestyleManager(); - WritingMode wm = aReflowState.GetWritingMode(); - nscoord startEdge = 0; + bool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection); + nscoord leftEdge = 0; // Don't offset by our start borderpadding if we have a prev continuation or // if we're in a part of an {ib} split other than the first one. if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) { - startEdge = aReflowState.ComputedLogicalBorderPadding().IStart(wm); + leftEdge = ltr ? aReflowState.ComputedPhysicalBorderPadding().left + : aReflowState.ComputedPhysicalBorderPadding().right; } - nscoord availableISize = aReflowState.AvailableISize(); - NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE, + nscoord availableWidth = aReflowState.AvailableWidth(); + NS_ASSERTION(availableWidth != NS_UNCONSTRAINEDSIZE, "should no longer use available widths"); - // Subtract off inline axis border+padding from availableISize - availableISize -= startEdge; - availableISize -= aReflowState.ComputedLogicalBorderPadding().IEnd(wm); - lineLayout->BeginSpan(this, &aReflowState, startEdge, - startEdge + availableISize, &mBaseline); + // Subtract off left and right border+padding from availableWidth + availableWidth -= leftEdge; + availableWidth -= ltr ? aReflowState.ComputedPhysicalBorderPadding().right + : aReflowState.ComputedPhysicalBorderPadding().left; + lineLayout->BeginSpan(this, &aReflowState, leftEdge, + leftEdge + availableWidth, &mBaseline); // First reflow our principal children. nsIFrame* frame = mFrames.FirstChild(); @@ -644,7 +646,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, // line-height calculations. However, continuations of an inline // that are empty we force to empty so that things like collapsed // whitespace in an inline element don't affect the line-height. - aMetrics.ISize() = lineLayout->EndSpan(this); + aMetrics.Width() = lineLayout->EndSpan(this); // Compute final width. @@ -652,7 +654,8 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, // continuation or if we're in a part of an {ib} split other than the first // one. if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) { - aMetrics.ISize() += aReflowState.ComputedLogicalBorderPadding().IStart(wm); + aMetrics.Width() += ltr ? aReflowState.ComputedPhysicalBorderPadding().left + : aReflowState.ComputedPhysicalBorderPadding().right; } /* @@ -665,7 +668,8 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, if (NS_FRAME_IS_COMPLETE(aStatus) && !LastInFlow()->GetNextContinuation() && !FrameIsNonLastInIBSplit()) { - aMetrics.Width() += aReflowState.ComputedLogicalBorderPadding().IEnd(wm); + aMetrics.Width() += ltr ? aReflowState.ComputedPhysicalBorderPadding().right + : aReflowState.ComputedPhysicalBorderPadding().left; } nsRefPtr fm; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index b441e058cb6b..d79e0420610b 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -23,13 +23,12 @@ #include "nsLayoutUtils.h" #include "nsTextFrame.h" #include "nsStyleStructInlines.h" -#include "nsBidiPresUtils.h" #include #ifdef DEBUG -#undef NOISY_INLINEDIR_ALIGN -#undef NOISY_BLOCKDIR_ALIGN -#undef REALLY_NOISY_BLOCKDIR_ALIGN +#undef NOISY_HORIZONTAL_ALIGN +#undef NOISY_VERTICAL_ALIGN +#undef REALLY_NOISY_VERTICAL_ALIGN #undef NOISY_REFLOW #undef REALLY_NOISY_REFLOW #undef NOISY_PUSHING @@ -61,7 +60,7 @@ nsLineLayout::nsLineLayout(nsPresContext* aPresContext, mLastOptionalBreakPriority(gfxBreakPriority::eNoBreak), mLastOptionalBreakContentOffset(-1), mForceBreakContentOffset(-1), - mMinLineBSize(0), + mMinLineHeight(0), mTextIndent(0), mFirstLetterStyleOK(false), mIsTopOfPage(false), @@ -92,7 +91,7 @@ nsLineLayout::nsLineLayout(nsPresContext* aPresContext, mLineNumber = 0; mTotalPlacedFrames = 0; - mBStartEdge = 0; + mTopEdge = 0; mTrimmableWidth = 0; mInflationMinFontSize = @@ -134,34 +133,33 @@ HasPrevInFlow(nsIFrame *aFrame) } void -nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord, - nscoord aISize, nscoord aBSize, +nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY, + nscoord aWidth, nscoord aHeight, bool aImpactedByFloats, bool aIsTopOfPage, - WritingMode aWritingMode, - nscoord aContainerWidth) + uint8_t aDirection) { NS_ASSERTION(nullptr == mRootSpan, "bad linelayout user"); - NS_WARN_IF_FALSE(aISize != NS_UNCONSTRAINEDSIZE, + NS_WARN_IF_FALSE(aWidth != NS_UNCONSTRAINEDSIZE, "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); #ifdef DEBUG - if ((aISize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aISize)) { + if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) { nsFrame::ListTag(stdout, mBlockReflowState->frame); printf(": Init: bad caller: width WAS %d(0x%x)\n", - aISize, aISize); + aWidth, aWidth); } - if ((aBSize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aBSize)) { + if ((aHeight != NS_UNCONSTRAINEDSIZE) && CRAZY_HEIGHT(aHeight)) { nsFrame::ListTag(stdout, mBlockReflowState->frame); printf(": Init: bad caller: height WAS %d(0x%x)\n", - aBSize, aBSize); + aHeight, aHeight); } #endif #ifdef NOISY_REFLOW nsFrame::ListTag(stdout, mBlockReflowState->frame); printf(": BeginLineReflow: %d,%d,%d,%d impacted=%s %s\n", - aICoord, aBCoord, aISize, aBSize, + aX, aY, aWidth, aHeight, aImpactedByFloats?"true":"false", aIsTopOfPage ? "top-of-page" : ""); #endif @@ -177,7 +175,7 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord, mLineAtStart = true; mLineEndsInBR = false; mSpanDepth = 0; - mMaxStartBoxBSize = mMaxEndBoxBSize = 0; + mMaxTopBoxHeight = mMaxBottomBoxHeight = 0; if (mGotLineBox) { mLineBox->ClearHasBullet(); @@ -186,10 +184,9 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord, PerSpanData* psd = NewPerSpanData(); mCurrentSpan = mRootSpan = psd; psd->mReflowState = mBlockReflowState; - psd->mIStart = aICoord; - psd->mICoord = aICoord; - psd->mIEnd = aICoord + aISize; - mContainerWidth = aContainerWidth; + psd->mLeftEdge = aX; + psd->mX = aX; + psd->mRightEdge = aX + aWidth; // If we're in a constrained height frame, then we don't allow a // max line box width to take effect. @@ -203,16 +200,17 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord, LineContainerFrame()->PresContext()->PresShell()->MaxLineBoxWidth(); if (maxLineBoxWidth > 0 && - psd->mIEnd - psd->mIStart > maxLineBoxWidth) { - psd->mIEnd = psd->mIStart + maxLineBoxWidth; + psd->mRightEdge - psd->mLeftEdge > maxLineBoxWidth) { + psd->mRightEdge = psd->mLeftEdge + maxLineBoxWidth; } } - mBStartEdge = aBCoord; + mTopEdge = aY; psd->mNoWrap = !mStyleText->WhiteSpaceCanWrapStyle() || LineContainerFrame()->IsSVGText(); - psd->mWritingMode = aWritingMode; + psd->mDirection = aDirection; + psd->mChangedFrameDirection = false; // If this is the first line of a block then see if the text-indent // property amounts to anything. @@ -232,7 +230,12 @@ nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord, mTextIndent = indent; - psd->mICoord += indent; + if (NS_STYLE_DIRECTION_RTL == psd->mDirection) { + psd->mRightEdge -= indent; + } + else { + psd->mX += indent; + } } } @@ -241,7 +244,7 @@ nsLineLayout::EndLineReflow() { #ifdef NOISY_REFLOW nsFrame::ListTag(stdout, mBlockReflowState->frame); - printf(": EndLineReflow: width=%d\n", mRootSpan->mICoord - mRootSpan->mIStart); + printf(": EndLineReflow: width=%d\n", mRootSpan->mX - mRootSpan->mLeftEdge); #endif FreeSpan(mRootSpan); @@ -265,76 +268,69 @@ nsLineLayout::EndLineReflow() } // XXX swtich to a single mAvailLineWidth that we adjust as each frame -// on the line is placed. Each span can still have a per-span mICoord that +// on the line is placed. Each span can still have a per-span mX that // tracks where a child frame is going in its span; they don't need a -// per-span mIStart? +// per-span mLeftEdge? void nsLineLayout::UpdateBand(const nsRect& aNewAvailSpace, nsIFrame* aFloatFrame) { - WritingMode lineWM = mRootSpan->mWritingMode; - LogicalRect availSpace(lineWM, aNewAvailSpace, mContainerWidth); #ifdef REALLY_NOISY_REFLOW - printf("nsLL::UpdateBand %d, %d, %d, %d, (logical %d, %d, %d, %d); frame=%p\n will set mImpacted to true\n", + printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p\n will set mImpacted to true\n", aNewAvailSpace.x, aNewAvailSpace.y, aNewAvailSpace.width, aNewAvailSpace.height, - availSpace.IStart(lineWM), availSpace.BStart(lineWM), - availSpace.ISize(lineWM), availSpace.BSize(lineWM), aFloatFrame); #endif #ifdef DEBUG - if ((availSpace.ISize(lineWM) != NS_UNCONSTRAINEDSIZE) && - CRAZY_SIZE(availSpace.ISize(lineWM))) { + if ((aNewAvailSpace.width != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aNewAvailSpace.width)) { nsFrame::ListTag(stdout, mBlockReflowState->frame); - printf(": UpdateBand: bad caller: ISize WAS %d(0x%x)\n", - availSpace.ISize(lineWM), availSpace.ISize(lineWM)); + printf(": UpdateBand: bad caller: width WAS %d(0x%x)\n", + aNewAvailSpace.width, aNewAvailSpace.width); } - if ((availSpace.BSize(lineWM) != NS_UNCONSTRAINEDSIZE) && - CRAZY_SIZE(availSpace.BSize(lineWM))) { + if ((aNewAvailSpace.height != NS_UNCONSTRAINEDSIZE) && CRAZY_HEIGHT(aNewAvailSpace.height)) { nsFrame::ListTag(stdout, mBlockReflowState->frame); - printf(": UpdateBand: bad caller: BSize WAS %d(0x%x)\n", - availSpace.BSize(lineWM), availSpace.BSize(lineWM)); + printf(": UpdateBand: bad caller: height WAS %d(0x%x)\n", + aNewAvailSpace.height, aNewAvailSpace.height); } #endif // Compute the difference between last times width and the new width - NS_WARN_IF_FALSE(mRootSpan->mIEnd != NS_UNCONSTRAINEDSIZE && + NS_WARN_IF_FALSE(mRootSpan->mRightEdge != NS_UNCONSTRAINEDSIZE && aNewAvailSpace.width != NS_UNCONSTRAINEDSIZE, "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); - // The root span's mIStart moves to aICoord - nscoord deltaICoord = availSpace.IStart(lineWM) - mRootSpan->mIStart; + // The root span's mLeftEdge moves to aX + nscoord deltaX = aNewAvailSpace.x - mRootSpan->mLeftEdge; // The width of all spans changes by this much (the root span's - // mIEnd moves to aICoord + aISize, its new width is aISize) - nscoord deltaISize = availSpace.ISize(lineWM) - - (mRootSpan->mIEnd - mRootSpan->mIStart); + // mRightEdge moves to aX + aWidth, its new width is aWidth) + nscoord deltaWidth = aNewAvailSpace.width - (mRootSpan->mRightEdge - mRootSpan->mLeftEdge); #ifdef NOISY_REFLOW nsFrame::ListTag(stdout, mBlockReflowState->frame); - printf(": UpdateBand: %d,%d,%d,%d deltaISize=%d deltaICoord=%d\n", + printf(": UpdateBand: %d,%d,%d,%d deltaWidth=%d deltaX=%d\n", aNewAvailSpace.x, aNewAvailSpace.y, - aNewAvailSpace.width, aNewAvailSpace.height, deltaISize, deltaICoord); + aNewAvailSpace.width, aNewAvailSpace.height, deltaWidth, deltaX); #endif // Update the root span position - mRootSpan->mIStart += deltaICoord; - mRootSpan->mIEnd += deltaICoord; - mRootSpan->mICoord += deltaICoord; + mRootSpan->mLeftEdge += deltaX; + mRootSpan->mRightEdge += deltaX; + mRootSpan->mX += deltaX; // Now update the right edges of the open spans to account for any // change in available space width for (PerSpanData* psd = mCurrentSpan; psd; psd = psd->mParent) { - psd->mIEnd += deltaISize; + psd->mRightEdge += deltaWidth; psd->mContainsFloat = true; #ifdef NOISY_REFLOW - printf(" span %p: oldIEnd=%d newIEnd=%d\n", - psd, psd->mIEnd - deltaISize, psd->mIEnd); + printf(" span %p: oldRightEdge=%d newRightEdge=%d\n", + psd, psd->mRightEdge - deltaRightEdge, psd->mRightEdge); #endif } NS_ASSERTION(mRootSpan->mContainsFloat && - mRootSpan->mIStart == availSpace.IStart(lineWM) && - mRootSpan->mIEnd == availSpace.IEnd(lineWM), + mRootSpan->mLeftEdge == aNewAvailSpace.x && + mRootSpan->mRightEdge == aNewAvailSpace.XMost(), "root span was updated incorrectly?"); // Update frame bounds @@ -342,13 +338,13 @@ nsLineLayout::UpdateBand(const nsRect& aNewAvailSpace, // children of the block), not the ones in the child spans. The reason // is simple: the frames in the spans have coordinates local to their // parent therefore they are moved when their parent span is moved. - if (deltaICoord != 0) { + if (deltaX != 0) { for (PerFrameData* pfd = mRootSpan->mFirstFrame; pfd; pfd = pfd->mNext) { - pfd->mBounds.IStart(lineWM) += deltaICoord; + pfd->mBounds.x += deltaX; } } - mBStartEdge = aNewAvailSpace.y; + mTopEdge = aNewAvailSpace.y; mImpactedByFloats = true; mLastFloatWasLetterFrame = nsGkAtoms::letterFrame == aFloatFrame->GetType(); @@ -386,15 +382,15 @@ nsLineLayout::NewPerSpanData() void nsLineLayout::BeginSpan(nsIFrame* aFrame, const nsHTMLReflowState* aSpanReflowState, - nscoord aIStart, nscoord aIEnd, + nscoord aLeftEdge, nscoord aRightEdge, nscoord* aBaseline) { - NS_ASSERTION(aIEnd != NS_UNCONSTRAINEDSIZE, + NS_ASSERTION(aRightEdge != NS_UNCONSTRAINEDSIZE, "should no longer be using unconstrained sizes"); #ifdef NOISY_REFLOW nsFrame::IndentBy(stdout, mSpanDepth+1); nsFrame::ListTag(stdout, aFrame); - printf(": BeginSpan leftEdge=%d rightEdge=%d\n", aIStart, aIEnd); + printf(": BeginSpan leftEdge=%d rightEdge=%d\n", aLeftEdge, aRightEdge); #endif PerSpanData* psd = NewPerSpanData(); @@ -407,14 +403,15 @@ nsLineLayout::BeginSpan(nsIFrame* aFrame, psd->mFrame = pfd; psd->mParent = mCurrentSpan; psd->mReflowState = aSpanReflowState; - psd->mIStart = aIStart; - psd->mICoord = aIStart; - psd->mIEnd = aIEnd; + psd->mLeftEdge = aLeftEdge; + psd->mX = aLeftEdge; + psd->mRightEdge = aRightEdge; psd->mBaseline = aBaseline; nsIFrame* frame = aSpanReflowState->frame; psd->mNoWrap = !frame->StyleText()->WhiteSpaceCanWrap(frame); - psd->mWritingMode = aSpanReflowState->GetWritingMode(); + psd->mDirection = aSpanReflowState->mStyleVisibility->mDirection; + psd->mChangedFrameDirection = false; // Switch to new span mCurrentSpan = psd; @@ -428,15 +425,15 @@ nsLineLayout::EndSpan(nsIFrame* aFrame) #ifdef NOISY_REFLOW nsFrame::IndentBy(stdout, mSpanDepth); nsFrame::ListTag(stdout, aFrame); - printf(": EndSpan width=%d\n", mCurrentSpan->mICoord - mCurrentSpan->mIStart); + printf(": EndSpan width=%d\n", mCurrentSpan->mX - mCurrentSpan->mLeftEdge); #endif PerSpanData* psd = mCurrentSpan; - nscoord iSizeResult = psd->mLastFrame ? (psd->mICoord - psd->mIStart) : 0; + nscoord widthResult = psd->mLastFrame ? (psd->mX - psd->mLeftEdge) : 0; mSpanDepth--; mCurrentSpan->mReflowState = nullptr; // no longer valid so null it out! mCurrentSpan = mCurrentSpan->mParent; - return iSizeResult; + return widthResult; } int32_t @@ -564,12 +561,12 @@ nsLineLayout::FreeSpan(PerSpanData* psd) } bool -nsLineLayout::IsZeroBSize() +nsLineLayout::IsZeroHeight() { PerSpanData* psd = mCurrentSpan; PerFrameData* pfd = psd->mFirstFrame; while (nullptr != pfd) { - if (0 != pfd->mBounds.BSize(psd->mWritingMode)) { + if (0 != pfd->mBounds.height) { return false; } pfd = pfd->mNext; @@ -578,7 +575,7 @@ nsLineLayout::IsZeroBSize() } nsLineLayout::PerFrameData* -nsLineLayout::NewPerFrameData(nsIFrame* aFrame) +nsLineLayout::NewPerFrameData() { PerFrameData* pfd = mFrameFreeList; if (!pfd) { @@ -595,18 +592,11 @@ nsLineLayout::NewPerFrameData(nsIFrame* aFrame) pfd->mSpan = nullptr; pfd->mNext = nullptr; pfd->mPrev = nullptr; + pfd->mFrame = nullptr; pfd->mFlags = 0; // all flags default to false - pfd->mFrame = aFrame; - - WritingMode frameWM = aFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; - pfd->mBounds = LogicalRect(lineWM); - pfd->mMargin = LogicalMargin(frameWM); - pfd->mBorderPadding = LogicalMargin(frameWM); - pfd->mOffsets = LogicalMargin(frameWM); #ifdef DEBUG - pfd->mBlockDirAlign = 0xFF; + pfd->mVerticalAlign = 0xFF; mFramesAllocated++; #endif return pfd; @@ -720,7 +710,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // Initialize OUT parameter aPushedFrame = false; - PerFrameData* pfd = NewPerFrameData(aFrame); + PerFrameData* pfd = NewPerFrameData(); PerSpanData* psd = mCurrentSpan; psd->AppendFrame(pfd); @@ -735,16 +725,15 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, mTextJustificationNumLetters = 0; // Stash copies of some of the computed state away for later - // (block-direction alignment, for example) - WritingMode frameWM = aFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; + // (vertical alignment, for example) + pfd->mFrame = aFrame; // NOTE: While the x coordinate remains relative to the parent span, // the y coordinate is fixed at the top edge for the line. During - // BlockDirAlignFrames we will repair this so that the y coordinate + // VerticalAlignFrames we will repair this so that the y coordinate // is properly set and relative to the appropriate span. - pfd->mBounds.IStart(lineWM) = psd->mICoord; - pfd->mBounds.BStart(lineWM) = mBStartEdge; + pfd->mBounds.x = psd->mX; + pfd->mBounds.y = mTopEdge; // We want to guarantee that we always make progress when // formatting. Therefore, if the object being placed on the line is @@ -770,11 +759,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // Inline-ish and text-ish things don't compute their width; // everything else does. We need to give them an available width that // reflects the space left on the line. - NS_WARN_IF_FALSE(psd->mIEnd != NS_UNCONSTRAINEDSIZE, + NS_WARN_IF_FALSE(psd->mRightEdge != NS_UNCONSTRAINEDSIZE, "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); - nscoord availableSpaceOnLine = psd->mIEnd - psd->mICoord; + nscoord availableSpaceOnLine = psd->mRightEdge - psd->mX; // Setup reflow state for reflowing the frame Maybe reflowStateHolder; @@ -786,24 +775,24 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, reflowState.mFlags.mIsTopOfPage = mIsTopOfPage; if (reflowState.ComputedWidth() == NS_UNCONSTRAINEDSIZE) reflowState.AvailableWidth() = availableSpaceOnLine; - WritingMode stateWM = reflowState.GetWritingMode(); - pfd->mMargin = - reflowState.ComputedLogicalMargin().ConvertTo(frameWM, stateWM); - pfd->mBorderPadding = - reflowState.ComputedLogicalBorderPadding().ConvertTo(frameWM, stateWM); + pfd->mMargin = reflowState.ComputedPhysicalMargin(); + pfd->mBorderPadding = reflowState.ComputedPhysicalBorderPadding(); pfd->SetFlag(PFD_RELATIVEPOS, reflowState.mStyleDisplay->IsRelativelyPositionedStyle()); if (pfd->GetFlag(PFD_RELATIVEPOS)) { - pfd->mOffsets = - reflowState.ComputedLogicalOffsets().ConvertTo(frameWM, stateWM); + pfd->mOffsets = reflowState.ComputedPhysicalOffsets(); } // Apply start margins (as appropriate) to the frame computing the // new starting x,y coordinates for the frame. ApplyStartMargin(pfd, reflowState); + } else { + pfd->mMargin.SizeTo(0, 0, 0, 0); + pfd->mBorderPadding.SizeTo(0, 0, 0, 0); + pfd->mOffsets.SizeTo(0, 0, 0, 0); + // Text reflow doesn't look at the dirty bits on the frame being reflowed, + // so no need to propagate NS_FRAME_IS_DIRTY from the parent. } - // if isText(), no need to propagate NS_FRAME_IS_DIRTY from the parent, - // because reflow doesn't look at the dirty bits on the frame being reflowed. // See if this frame depends on the width of its containing block. If // so, disable resize reflow optimizations for the line. (Note that, @@ -818,18 +807,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // Let frame know that are reflowing it. Note that we don't bother // positioning the frame yet, because we're probably going to end up - // moving it when we do the block-direction alignment + // moving it when we do the vertical alignment aFrame->WillReflow(mPresContext); // Adjust spacemanager coordinate system for the frame. - nsHTMLReflowMetrics metrics(lineWM); + nsHTMLReflowMetrics metrics(mBlockReflowState->GetWritingMode()); #ifdef DEBUG metrics.Width() = nscoord(0xdeadbeef); metrics.Height() = nscoord(0xdeadbeef); #endif - nsRect physicalBounds = pfd->mBounds.GetPhysicalRect(lineWM, mContainerWidth); - nscoord tx = physicalBounds.x; - nscoord ty = physicalBounds.y; + nscoord tx = pfd->mBounds.x; + nscoord ty = pfd->mBounds.y; mFloatManager->Translate(tx, ty); int32_t savedOptionalBreakOffset; @@ -870,7 +858,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // Add mTrimmableWidth to the available width since if the line ends // here, the width of the inline content will be reduced by // mTrimmableWidth. - nscoord availableWidth = psd->mIEnd - (psd->mICoord - mTrimmableWidth); + nscoord availableWidth = psd->mRightEdge - (psd->mX - mTrimmableWidth); if (psd->mNoWrap) { // If we place floats after inline content where there's // no break opportunity, we don't know how much additional @@ -931,7 +919,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // Note: break-before means ignore the reflow metrics since the // frame will be reflowed another time. if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) { - if (CRAZY_SIZE(metrics.Width()) || CRAZY_SIZE(metrics.Height())) { + if (CRAZY_WIDTH(metrics.Width()) || CRAZY_HEIGHT(metrics.Height())) { printf("nsLineLayout: "); nsFrame::ListTag(stdout, aFrame); printf(" metrics=%d,%d!\n", metrics.Width(), metrics.Height()); @@ -952,8 +940,8 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, // added in later by nsLineLayout::ReflowInlineFrames. pfd->mOverflowAreas = metrics.mOverflowAreas; - pfd->mBounds.ISize(lineWM) = metrics.ISize(); - pfd->mBounds.BSize(lineWM) = metrics.BSize(); + pfd->mBounds.width = metrics.Width(); + pfd->mBounds.height = metrics.Height(); // Size the frame, but |RelativePositionFrames| will size the view. aFrame->SetSize(nsSize(metrics.Width(), metrics.Height())); @@ -1000,7 +988,13 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, !reflowStateHolder.ref().IsFloating(), "How'd we get a floated inline frame? " "The frame ctor should've dealt with this."); - if (CanPlaceFrame(pfd, notSafeToBreak, continuingTextRun, + // Direction is inherited, so using the psd direction is fine. + // Get it off the reflow state instead of the frame to save style + // data computation (especially for the text). + uint8_t direction = + isText ? psd->mReflowState->mStyleVisibility->mDirection : + reflowStateHolder.ref().mStyleVisibility->mDirection; + if (CanPlaceFrame(pfd, direction, notSafeToBreak, continuingTextRun, savedOptionalBreakContent != nullptr, metrics, aReflowStatus, &optionalBreakAfterFits)) { if (!isEmpty) { @@ -1019,9 +1013,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, PerSpanData* span = pfd->mSpan; if (span) { // The frame we just finished reflowing is an inline - // container. It needs its child frames aligned in the block direction, + // container. It needs its child frames vertically aligned, // so do most of it now. - BlockDirAlignFrames(span); + VerticalAlignFrames(span); } if (!continuingTextRun) { @@ -1068,8 +1062,8 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd, "How'd we get a floated inline frame? " "The frame ctor should've dealt with this."); - WritingMode frameWM = pfd->mFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; + // XXXwaterson probably not the right way to get this; e.g., embeddings, etc. + bool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection); // Only apply start-margin on the first-in flow for inline frames, // and make sure to not apply it to any inline other than the first @@ -1081,21 +1075,13 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd, pfd->mFrame->FrameIsNonFirstInIBSplit()) { // Zero this out so that when we compute the max-element-width of // the frame we will properly avoid adding in the starting margin. - pfd->mMargin.IStart(frameWM) = 0; + if (ltr) + pfd->mMargin.left = 0; + else + pfd->mMargin.right = 0; } - if ((pfd->mFrame->LastInFlow()->GetNextContinuation() || - pfd->mFrame->FrameIsNonLastInIBSplit()) - && !pfd->GetFlag(PFD_ISLETTERFRAME)) { - pfd->mMargin.IEnd(frameWM) = 0; - } - nscoord startMargin = pfd->mMargin.ConvertTo(lineWM, frameWM).IStart(lineWM); - if (startMargin) { - // In RTL mode, we will only apply the start margin to the frame bounds - // after we finish flowing the frame and know more accurately whether we - // want to skip the margins. - if (lineWM.IsBidiLTR() && frameWM.IsBidiLTR()) { - pfd->mBounds.IStart(lineWM) += startMargin; - } + else { + pfd->mBounds.x += ltr ? pfd->mMargin.left : pfd->mMargin.right; NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.AvailableWidth(), "have unconstrained width; this should only result from " @@ -1104,20 +1090,20 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd, if (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth()) { // For inline-ish and text-ish things (which don't compute widths // in the reflow state), adjust available width to account for the - // start margin. The end margin will be accounted for when we + // left margin. The right margin will be accounted for when we // finish flowing the frame. - aReflowState.AvailableWidth() -= startMargin; + aReflowState.AvailableWidth() -= ltr ? pfd->mMargin.left : pfd->mMargin.right; } } } nscoord -nsLineLayout::GetCurrentFrameInlineDistanceFromBlock() +nsLineLayout::GetCurrentFrameXDistanceFromBlock() { PerSpanData* psd; nscoord x = 0; for (psd = mCurrentSpan; psd; psd = psd->mParent) { - x += psd->mICoord; + x += psd->mX; } return x; } @@ -1134,6 +1120,7 @@ nsLineLayout::GetCurrentFrameInlineDistanceFromBlock() */ bool nsLineLayout::CanPlaceFrame(PerFrameData* pfd, + uint8_t aFrameDirection, bool aNotSafeToBreak, bool aFrameCanContinueTextRun, bool aCanRollBackBeforeFrame, @@ -1142,9 +1129,12 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, bool* aOptionalBreakAfterFits) { NS_PRECONDITION(pfd && pfd->mFrame, "bad args, null pointers for frame data"); + + *aOptionalBreakAfterFits = true; + + // XXXwaterson this is probably not exactly right; e.g., embeddings, etc. + bool ltr = NS_STYLE_DIRECTION_LTR == aFrameDirection; - WritingMode frameWM = pfd->mFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; /* * We want to only apply the end margin if we're the last continuation and * either not in an {ib} split or the last inline in it. In all other @@ -1159,22 +1149,15 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, * * However, none of that applies if this is a letter frame (XXXbz why?) */ - if (pfd->mFrame->GetPrevContinuation() || - pfd->mFrame->FrameIsNonFirstInIBSplit()) { - pfd->mMargin.IStart(frameWM) = 0; - } if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) || pfd->mFrame->LastInFlow()->GetNextContinuation() || pfd->mFrame->FrameIsNonLastInIBSplit()) && !pfd->GetFlag(PFD_ISLETTERFRAME)) { - pfd->mMargin.IEnd(frameWM) = 0; - } - LogicalMargin usedMargins = pfd->mMargin.ConvertTo(lineWM, frameWM); - nscoord startMargin = usedMargins.IStart(lineWM); - nscoord endMargin = usedMargins.IEnd(lineWM); - - if (!(lineWM.IsBidiLTR() && frameWM.IsBidiLTR())) { - pfd->mBounds.IStart(lineWM) += startMargin; + if (ltr) { + pfd->mMargin.right = 0; + } else { + pfd->mMargin.left = 0; + } } PerSpanData* psd = mCurrentSpan; @@ -1183,6 +1166,8 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, return true; } + nscoord endMargin = ltr ? pfd->mMargin.right : pfd->mMargin.left; + #ifdef NOISY_CAN_PLACE_FRAME if (nullptr != psd->mFrame) { nsFrame::ListTag(stdout, psd->mFrame->mFrame); @@ -1192,15 +1177,12 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, } printf(": aNotSafeToBreak=%s frame=", aNotSafeToBreak ? "true" : "false"); nsFrame::ListTag(stdout, pfd->mFrame); - printf(" frameWidth=%d, margins=%d,%d\n", - pfd->mBounds.IEnd(lineWM) + endMargin - psd->mICoord, - startMargin, endMargin); + printf(" frameWidth=%d\n", pfd->mBounds.XMost() + endMargin - psd->mX); #endif // Set outside to true if the result of the reflow leads to the // frame sticking outside of our available area. - bool outside = pfd->mBounds.IEnd(lineWM) - mTrimmableWidth + endMargin > - psd->mIEnd; + bool outside = pfd->mBounds.XMost() - mTrimmableWidth + endMargin > psd->mRightEdge; if (!outside) { // If it fits, it fits #ifdef NOISY_CAN_PLACE_FRAME @@ -1212,7 +1194,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, // When it doesn't fit, check for a few special conditions where we // allow it to fit anyway. - if (0 == startMargin + pfd->mBounds.ISize(lineWM) + endMargin) { + if (0 == pfd->mMargin.left + pfd->mBounds.width + pfd->mMargin.right) { // Empty frames always fit right where they are #ifdef NOISY_CAN_PLACE_FRAME printf(" ==> empty frame fits\n"); @@ -1237,7 +1219,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, #ifdef NOISY_CAN_PLACE_FRAME printf(" ==> not-safe and not-impacted fits: "); while (nullptr != psd) { - printf(" ", psd, psd->mICoord, psd->mIStart); + printf(" ", psd, psd->mX, psd->mLeftEdge); psd = psd->mParent; } printf("\n"); @@ -1306,16 +1288,14 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics) else pfd->mAscent = aMetrics.TopAscent(); - // Advance to next inline coordinate - WritingMode frameWM = pfd->mFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; - mCurrentSpan->mICoord = pfd->mBounds.IEnd(lineWM) + - pfd->mMargin.ConvertTo(lineWM, frameWM).IEnd(lineWM); + bool ltr = (NS_STYLE_DIRECTION_LTR == pfd->mFrame->StyleVisibility()->mDirection); + // Advance to next X coordinate + mCurrentSpan->mX = pfd->mBounds.XMost() + + (ltr ? pfd->mMargin.right : pfd->mMargin.left); // Count the number of non-placeholder frames on the line... if (pfd->mFrame->GetType() == nsGkAtoms::placeholderFrame) { - NS_ASSERTION(pfd->mBounds.ISize(lineWM) == 0 && - pfd->mBounds.BSize(lineWM) == 0, + NS_ASSERTION(pfd->mBounds.width == 0 && pfd->mBounds.height == 0, "placeholders should have 0 width/height (checking " "placeholders were never counted by the old code in " "this function)"); @@ -1339,17 +1319,20 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame, mLineBox->SetHasBullet(); } - PerFrameData* pfd = NewPerFrameData(aFrame); + PerFrameData* pfd = NewPerFrameData(); mRootSpan->AppendFrame(pfd); + pfd->mFrame = aFrame; + pfd->mMargin.SizeTo(0, 0, 0, 0); + pfd->mBorderPadding.SizeTo(0, 0, 0, 0); + pfd->mFlags = 0; // all flags default to false pfd->SetFlag(PFD_ISBULLET, true); if (aMetrics.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) pfd->mAscent = aFrame->GetBaseline(); else pfd->mAscent = aMetrics.TopAscent(); - // Note: block-coord value will be updated during block-direction alignment - pfd->mBounds = LogicalRect(mRootSpan->mWritingMode, - aFrame->GetRect(), mContainerWidth); + // Note: y value will be updated during vertical alignment + pfd->mBounds = aFrame->GetRect(); pfd->mOverflowAreas = aMetrics.mOverflowAreas; } @@ -1359,14 +1342,13 @@ nsLineLayout::DumpPerSpanData(PerSpanData* psd, int32_t aIndent) { nsFrame::IndentBy(stdout, aIndent); printf("%p: left=%d x=%d right=%d\n", static_cast(psd), - psd->mIStart, psd->mICoord, psd->mIEnd); + psd->mLeftEdge, psd->mX, psd->mRightEdge); PerFrameData* pfd = psd->mFirstFrame; while (nullptr != pfd) { nsFrame::IndentBy(stdout, aIndent+1); nsFrame::ListTag(stdout, pfd->mFrame); - nsRect rect = pfd->mBounds.GetPhysicalRect(psd->mWritingMode, - mContainerWidth); - printf(" %d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height); + printf(" %d,%d,%d,%d\n", pfd->mBounds.x, pfd->mBounds.y, + pfd->mBounds.width, pfd->mBounds.height); if (pfd->mSpan) { DumpPerSpanData(pfd->mSpan, aIndent + 1); } @@ -1380,10 +1362,10 @@ nsLineLayout::DumpPerSpanData(PerSpanData* psd, int32_t aIndent) #define VALIGN_BOTTOM 2 void -nsLineLayout::BlockDirAlignLine() +nsLineLayout::VerticalAlignLine() { // Synthesize a PerFrameData for the block frame - PerFrameData rootPFD(mBlockReflowState->frame->GetWritingMode()); + PerFrameData rootPFD; rootPFD.mFrame = mBlockReflowState->frame; rootPFD.mAscent = 0; mRootSpan->mFrame = &rootPFD; @@ -1392,86 +1374,80 @@ nsLineLayout::BlockDirAlignLine() // this operation is set to zero so that the y coordinates for all // of the placed children will be relative to there. PerSpanData* psd = mRootSpan; - BlockDirAlignFrames(psd); + VerticalAlignFrames(psd); - // *** Note that comments here still use the anachronistic term "line-height" - // when we really mean "size of the line in the block direction". This is - // partly for brevity and partly to retain the association with the CSS - // line-height property - // // Compute the line-height. The line-height will be the larger of: // - // [1] maxBCoord - minBCoord (the distance between the first child's - // block-start edge and the last child's block-end edge) + // [1] maxY - minY (the distance between the highest childs top edge + // and the lowest childs bottom edge) // - // [2] the maximum logical box block size (since not every frame may have - // participated in #1; for example: block-start/end aligned frames) + // [2] the maximum logical box height (since not every frame may have + // participated in #1; for example: top/bottom aligned frames) // - // [3] the minimum line height ("line-height" property set on the + // [3] the minimum line height (line-height property set on the // block frame) - nscoord lineBSize = psd->mMaxBCoord - psd->mMinBCoord; + nscoord lineHeight = psd->mMaxY - psd->mMinY; // Now that the line-height is computed, we need to know where the - // baseline is in the line. Position baseline so that mMinBCoord is just - // inside the start of the line box. - nscoord baselineBCoord; - if (psd->mMinBCoord < 0) { - baselineBCoord = mBStartEdge - psd->mMinBCoord; + // baseline is in the line. Position baseline so that mMinY is just + // inside the top of the line box. + nscoord baselineY; + if (psd->mMinY < 0) { + baselineY = mTopEdge - psd->mMinY; } else { - baselineBCoord = mBStartEdge; + baselineY = mTopEdge; } - // It's also possible that the line block-size isn't tall enough because - // of block start/end aligned elements that were not accounted for in - // min/max BCoord. + // It's also possible that the line-height isn't tall enough because + // of top/bottom aligned elements that were not accounted for in + // min/max Y. // // The CSS2 spec doesn't really say what happens when to the - // baseline in this situations. What we do is if the largest start - // aligned box block size is greater than the line block-size then we leave - // the baseline alone. If the largest end aligned box is greater - // than the line block-size then we slide the baseline forward by the extra + // baseline in this situations. What we do is if the largest top + // aligned box height is greater than the line-height then we leave + // the baseline alone. If the largest bottom aligned box is greater + // than the line-height then we slide the baseline down by the extra // amount. // // Navigator 4 gives precedence to the first top/bottom aligned - // object. We just let block end aligned objects win. - if (lineBSize < mMaxEndBoxBSize) { - // When the line is shorter than the maximum block start aligned box - nscoord extra = mMaxEndBoxBSize - lineBSize; - baselineBCoord += extra; - lineBSize = mMaxEndBoxBSize; + // object. We just let bottom aligned objects win. + if (lineHeight < mMaxBottomBoxHeight) { + // When the line is shorter than the maximum top aligned box + nscoord extra = mMaxBottomBoxHeight - lineHeight; + baselineY += extra; + lineHeight = mMaxBottomBoxHeight; } - if (lineBSize < mMaxStartBoxBSize) { - lineBSize = mMaxStartBoxBSize; + if (lineHeight < mMaxTopBoxHeight) { + lineHeight = mMaxTopBoxHeight; } -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" [line]==> lineBSize=%d baselineBCoord=%d\n", lineBSize, baselineBCoord); +#ifdef NOISY_VERTICAL_ALIGN + printf(" [line]==> lineHeight=%d baselineY=%d\n", lineHeight, baselineY); #endif // Now position all of the frames in the root span. We will also - // recurse over the child spans and place any block start/end aligned + // recurse over the child spans and place any top/bottom aligned // frames we find. // XXX PERFORMANCE: set a bit per-span to avoid the extra work // (propagate it upward too) - WritingMode lineWM = psd->mWritingMode; for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) { - if (pfd->mBlockDirAlign == VALIGN_OTHER) { - pfd->mBounds.BStart(lineWM) += baselineBCoord; - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); + if (pfd->mVerticalAlign == VALIGN_OTHER) { + pfd->mBounds.y += baselineY; + pfd->mFrame->SetRect(pfd->mBounds); } } - PlaceStartEndFrames(psd, -mBStartEdge, lineBSize); + PlaceTopBottomFrames(psd, -mTopEdge, lineHeight); // If the frame being reflowed has text decorations, we simulate the // propagation of those decorations to a line-level element by storing the - // offset in a frame property on any child frames that are aligned in the - // block direction somewhere other than the baseline. This property is then - // used by nsTextFrame::GetTextDecorations when the same conditions are met. + // offset in a frame property on any child frames that are vertically-aligned + // somewhere other than the baseline. This property is then used by + // nsTextFrame::GetTextDecorations when the same conditions are met. if (rootPFD.mFrame->StyleContext()->HasTextDecorationLines()) { for (const PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) { const nsIFrame *const f = pfd->mFrame; if (f->VerticalAlignEnum() != NS_STYLE_VERTICAL_ALIGN_BASELINE) { - const nscoord offset = baselineBCoord - pfd->mBounds.BStart(lineWM); + const nscoord offset = baselineY - pfd->mBounds.y; f->Properties().Set(nsIFrame::LineBaselineOffset(), NS_INT32_TO_PTR(offset)); } @@ -1479,19 +1455,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; - - mFinalLineBSize = lineBSize; - mLineBox->SetAscent(baselineBCoord - mBStartEdge); -#ifdef NOISY_BLOCKDIR_ALIGN + mLineBox->mBounds.x = psd->mLeftEdge; + mLineBox->mBounds.y = mTopEdge; + mLineBox->mBounds.width = psd->mX - psd->mLeftEdge; + mLineBox->mBounds.height = lineHeight; + mFinalLineHeight = lineHeight; + mLineBox->SetAscent(baselineY - mTopEdge); +#ifdef NOISY_VERTICAL_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, - mFinalLineBSize, mLineBox->GetAscent()); + mFinalLineHeight, mLineBox->GetAscent()); #endif // Undo root-span mFrame pointer to prevent brane damage later on... @@ -1499,63 +1474,59 @@ nsLineLayout::BlockDirAlignLine() } void -nsLineLayout::PlaceStartEndFrames(PerSpanData* psd, - nscoord aDistanceFromStart, - nscoord aLineBSize) +nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, + nscoord aDistanceFromTop, + nscoord aLineHeight) { for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) { PerSpanData* span = pfd->mSpan; #ifdef DEBUG - NS_ASSERTION(0xFF != pfd->mBlockDirAlign, "umr"); + NS_ASSERTION(0xFF != pfd->mVerticalAlign, "umr"); #endif - WritingMode frameWM = pfd->mFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; - switch (pfd->mBlockDirAlign) { + switch (pfd->mVerticalAlign) { case VALIGN_TOP: if (span) { - pfd->mBounds.BStart(lineWM) = -aDistanceFromStart - span->mMinBCoord; + pfd->mBounds.y = -aDistanceFromTop - span->mMinY; } else { - pfd->mBounds.BStart(lineWM) = - -aDistanceFromStart + pfd->mMargin.BStart(frameWM); + pfd->mBounds.y = -aDistanceFromTop + pfd->mMargin.top; } - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); -#ifdef NOISY_BLOCKDIR_ALIGN + pfd->mFrame->SetRect(pfd->mBounds); +#ifdef NOISY_VERTICAL_ALIGN printf(" "); nsFrame::ListTag(stdout, pfd->mFrame); printf(": y=%d dTop=%d [bp.top=%d topLeading=%d]\n", - pfd->mBounds.BStart(lineWM), aDistanceFromStart, - span ? pfd->mBorderPadding.BStart(frameWM) : 0, - span ? span->mBStartLeading : 0); + pfd->mBounds.y, aDistanceFromTop, + span ? pfd->mBorderPadding.top : 0, + span ? span->mTopLeading : 0); #endif break; case VALIGN_BOTTOM: if (span) { // Compute bottom leading - pfd->mBounds.BStart(lineWM) = - -aDistanceFromStart + aLineBSize - span->mMaxBCoord; + pfd->mBounds.y = -aDistanceFromTop + aLineHeight - span->mMaxY; } else { - pfd->mBounds.BStart(lineWM) = -aDistanceFromStart + aLineBSize - - pfd->mMargin.BEnd(frameWM) - pfd->mBounds.BSize(lineWM); + pfd->mBounds.y = -aDistanceFromTop + aLineHeight - + pfd->mMargin.bottom - pfd->mBounds.height; } - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); -#ifdef NOISY_BLOCKDIR_ALIGN + pfd->mFrame->SetRect(pfd->mBounds); +#ifdef NOISY_VERTICAL_ALIGN printf(" "); nsFrame::ListTag(stdout, pfd->mFrame); - printf(": y=%d\n", pfd->mBounds.BStart(lineWM)); + printf(": y=%d\n", pfd->mBounds.y); #endif break; } if (span) { - nscoord fromStart = aDistanceFromStart + pfd->mBounds.BStart(lineWM); - PlaceStartEndFrames(span, fromStart, aLineBSize); + nscoord distanceFromTop = aDistanceFromTop + pfd->mBounds.y; + PlaceTopBottomFrames(span, distanceFromTop, aLineHeight); } } } static float -GetInflationForBlockDirAlignment(nsIFrame* aFrame, +GetInflationForVerticalAlignment(nsIFrame* aFrame, nscoord aInflationMinFontSize) { if (aFrame->IsSVGText()) { @@ -1568,15 +1539,15 @@ GetInflationForBlockDirAlignment(nsIFrame* aFrame, return nsLayoutUtils::FontSizeInflationInner(aFrame, aInflationMinFontSize); } -#define BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM nscoord_MAX -#define BLOCKDIR_ALIGN_FRAMES_NO_MAXIMUM nscoord_MIN +#define VERTICAL_ALIGN_FRAMES_NO_MINIMUM nscoord_MAX +#define VERTICAL_ALIGN_FRAMES_NO_MAXIMUM nscoord_MIN -// Place frames in the block direction within a given span. Note: this doesn't -// place block start/end aligned frames as those have to wait until the -// entire line box block size is known. This is called after the span -// frame has finished being reflowed so that we know its block size. +// Vertically place frames within a given span. Note: this doesn't +// place top/bottom aligned frames as those have to wait until the +// entire line box height is known. This is called after the span +// frame has finished being reflowed so that we know its height. void -nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) +nsLineLayout::VerticalAlignFrames(PerSpanData* psd) { // Get parent frame info PerFrameData* spanFramePFD = psd->mFrame; @@ -1585,7 +1556,7 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // Get the parent frame's font for all of the frames in this span nsRefPtr fm; float inflation = - GetInflationForBlockDirAlignment(spanFrame, mInflationMinFontSize); + GetInflationForVerticalAlignment(spanFrame, mInflationMinFontSize); nsLayoutUtils::GetFontMetricsForFrame(spanFrame, getter_AddRefs(fm), inflation); mBlockReflowState->rendContext->SetFont(fm); @@ -1596,32 +1567,28 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // - it has a prev-in-flow // - it has no next in flow // - it's zero sized - WritingMode frameWM = spanFramePFD->mFrame->GetWritingMode(); - WritingMode lineWM = mRootSpan->mWritingMode; bool emptyContinuation = psd != mRootSpan && spanFrame->GetPrevInFlow() && !spanFrame->GetNextInFlow() && - spanFramePFD->mBounds.IsZeroSize(); + (0 == spanFramePFD->mBounds.width) && (0 == spanFramePFD->mBounds.height); -#ifdef NOISY_BLOCKDIR_ALIGN +#ifdef NOISY_VERTICAL_ALIGN printf("[%sSpan]", (psd == mRootSpan)?"Root":""); nsFrame::ListTag(stdout, spanFrame); printf(": preMode=%s strictMode=%s w/h=%d,%d emptyContinuation=%s", preMode ? "yes" : "no", mPresContext->CompatibilityMode() != eCompatibility_NavQuirks ? "yes" : "no", - spanFramePFD->mBounds.ISize(lineWM), - spanFramePFD->mBounds.BSize(lineWM), + spanFramePFD->mBounds.width, spanFramePFD->mBounds.height, emptyContinuation ? "yes" : "no"); if (psd != mRootSpan) { - WritingMode frameWM = spanFramePFD->mFrame->GetWritingMode(); printf(" bp=%d,%d,%d,%d margin=%d,%d,%d,%d", - spanFramePFD->mBorderPadding.Top(frameWM), - spanFramePFD->mBorderPadding.Right(frameWM), - spanFramePFD->mBorderPadding.Bottom(frameWM), - spanFramePFD->mBorderPadding.Left(frameWM), - spanFramePFD->mMargin.Top(frameWM), - spanFramePFD->mMargin.Right(frameWM), - spanFramePFD->mMargin.Bottom(frameWM), - spanFramePFD->mMargin.Left(frameWM)); + spanFramePFD->mBorderPadding.top, + spanFramePFD->mBorderPadding.right, + spanFramePFD->mBorderPadding.bottom, + spanFramePFD->mBorderPadding.left, + spanFramePFD->mMargin.top, + spanFramePFD->mMargin.right, + spanFramePFD->mMargin.bottom, + spanFramePFD->mMargin.left); } printf("\n"); #endif @@ -1636,7 +1603,7 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // exception case is when a span is continued and yet the span is // empty (e.g. compressed whitespace). For this kind of span we treat // it as if it were not there so that it doesn't impact the - // line block-size. + // line-height. // // In almost standards mode or quirks mode, we should sometimes make // it disappear. The cases that matter are those where the span @@ -1663,8 +1630,14 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) if ((emptyContinuation || mPresContext->CompatibilityMode() != eCompatibility_FullStandards) && ((psd == mRootSpan) || - (spanFramePFD->mBorderPadding.IsEmpty() && - spanFramePFD->mMargin.IsEmpty()))) { + ((0 == spanFramePFD->mBorderPadding.top) && + (0 == spanFramePFD->mBorderPadding.right) && + (0 == spanFramePFD->mBorderPadding.bottom) && + (0 == spanFramePFD->mBorderPadding.left) && + (0 == spanFramePFD->mMargin.top) && + (0 == spanFramePFD->mMargin.right) && + (0 == spanFramePFD->mMargin.bottom) && + (0 == spanFramePFD->mMargin.left)))) { // This code handles an issue with compatibility with non-css // conformant browsers. In particular, there are some cases // where the font-size and line-height for a span must be @@ -1684,7 +1657,7 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) { if (pfd->GetFlag(PFD_ISTEXTFRAME) && (pfd->GetFlag(PFD_ISNONWHITESPACETEXTFRAME) || preMode || - pfd->mBounds.ISize(mRootSpan->mWritingMode) != 0)) { + pfd->mBounds.width != 0)) { zeroEffectiveSpanBox = false; break; } @@ -1692,52 +1665,51 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) } psd->mZeroEffectiveSpanBox = zeroEffectiveSpanBox; - // Setup baselineBCoord, minBCoord, and maxBCoord - nscoord baselineBCoord, minBCoord, maxBCoord; + // Setup baselineY, minY, and maxY + nscoord baselineY, minY, maxY; if (psd == mRootSpan) { - // Use a zero baselineBCoord since we don't yet know where the baseline + // Use a zero baselineY since we don't yet know where the baseline // will be (until we know how tall the line is; then we will - // know). In addition, use extreme values for the minBCoord and maxBCoord + // know). In addition, use extreme values for the minY and maxY // values so that only the child frames will impact their values // (since these are children of the block, there is no span box to // provide initial values). - baselineBCoord = 0; - minBCoord = BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM; - maxBCoord = BLOCKDIR_ALIGN_FRAMES_NO_MAXIMUM; -#ifdef NOISY_BLOCKDIR_ALIGN + baselineY = 0; + minY = VERTICAL_ALIGN_FRAMES_NO_MINIMUM; + maxY = VERTICAL_ALIGN_FRAMES_NO_MAXIMUM; +#ifdef NOISY_VERTICAL_ALIGN printf("[RootSpan]"); nsFrame::ListTag(stdout, spanFrame); - printf(": pass1 valign frames: topEdge=%d minLineBSize=%d zeroEffectiveSpanBox=%s\n", - mBStartEdge, mMinLineBSize, + printf(": pass1 valign frames: topEdge=%d minLineHeight=%d zeroEffectiveSpanBox=%s\n", + mTopEdge, mMinLineHeight, zeroEffectiveSpanBox ? "yes" : "no"); #endif } else { - // Compute the logical block size for this span. The logical block size - // is based on the "line-height" value, not the font-size. Also + // Compute the logical height for this span. The logical height + // is based on the line-height value, not the font-size. Also // compute the top leading. float inflation = - GetInflationForBlockDirAlignment(spanFrame, mInflationMinFontSize); - nscoord logicalBSize = nsHTMLReflowState:: + GetInflationForVerticalAlignment(spanFrame, mInflationMinFontSize); + nscoord logicalHeight = nsHTMLReflowState:: CalcLineHeight(spanFrame->StyleContext(), mBlockReflowState->ComputedHeight(), inflation); - nscoord contentBSize = spanFramePFD->mBounds.BSize(lineWM) - - spanFramePFD->mBorderPadding.BStart(frameWM) - - spanFramePFD->mBorderPadding.BEnd(frameWM); + nscoord contentHeight = spanFramePFD->mBounds.height - + spanFramePFD->mBorderPadding.top - spanFramePFD->mBorderPadding.bottom; // Special-case for a ::first-letter frame, set the line height to - // the frame block size if the user has left line-height == normal + // the frame height if the user has left line-height == normal if (spanFramePFD->GetFlag(PFD_ISLETTERFRAME) && !spanFrame->GetPrevInFlow() && spanFrame->StyleText()->mLineHeight.GetUnit() == eStyleUnit_Normal) { - logicalBSize = spanFramePFD->mBounds.BSize(lineWM); + logicalHeight = spanFramePFD->mBounds.height; } - nscoord leading = logicalBSize - contentBSize; - psd->mBStartLeading = leading / 2; - psd->mBEndLeading = leading - psd->mBStartLeading; - psd->mLogicalBSize = logicalBSize; + nscoord leading = logicalHeight - contentHeight; + psd->mTopLeading = leading / 2; + psd->mBottomLeading = leading - psd->mTopLeading; + psd->mLogicalHeight = logicalHeight; if (zeroEffectiveSpanBox) { // When the span-box is to be ignored, zero out the initial @@ -1747,45 +1719,42 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // Note that things are readjusted for this span after its children // are reflowed - minBCoord = BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM; - maxBCoord = BLOCKDIR_ALIGN_FRAMES_NO_MAXIMUM; + minY = VERTICAL_ALIGN_FRAMES_NO_MINIMUM; + maxY = VERTICAL_ALIGN_FRAMES_NO_MAXIMUM; } else { - // The initial values for the min and max block coord values are in the - // span's coordinate space, and cover the logical block size of the span. - // If there are child frames in this span that stick out of this area - // then the minBCoord and maxBCoord are updated by the amount of logical - // blockSize that is outside this range. - minBCoord = spanFramePFD->mBorderPadding.BStart(frameWM) - - psd->mBStartLeading; - maxBCoord = minBCoord + psd->mLogicalBSize; + // The initial values for the min and max Y values are in the spans + // coordinate space, and cover the logical height of the span. If + // there are child frames in this span that stick out of this area + // then the minY and maxY are updated by the amount of logical + // height that is outside this range. + minY = spanFramePFD->mBorderPadding.top - psd->mTopLeading; + maxY = minY + psd->mLogicalHeight; } // This is the distance from the top edge of the parents visual // box to the baseline. The span already computed this for us, // so just use it. - *psd->mBaseline = baselineBCoord = spanFramePFD->mAscent; + *psd->mBaseline = baselineY = spanFramePFD->mAscent; -#ifdef NOISY_BLOCKDIR_ALIGN +#ifdef NOISY_VERTICAL_ALIGN printf("[%sSpan]", (psd == mRootSpan)?"Root":""); nsFrame::ListTag(stdout, spanFrame); - printf(": baseLine=%d logicalBSize=%d topLeading=%d h=%d bp=%d,%d zeroEffectiveSpanBox=%s\n", - baselineBCoord, psd->mLogicalBSize, psd->mBStartLeading, - spanFramePFD->mBounds.BSize(lineWM), - spanFramePFD->mBorderPadding.Top(frameWM), - spanFramePFD->mBorderPadding.Bottom(frameWM), + printf(": baseLine=%d logicalHeight=%d topLeading=%d h=%d bp=%d,%d zeroEffectiveSpanBox=%s\n", + baselineY, psd->mLogicalHeight, psd->mTopLeading, + spanFramePFD->mBounds.height, + spanFramePFD->mBorderPadding.top, spanFramePFD->mBorderPadding.bottom, zeroEffectiveSpanBox ? "yes" : "no"); #endif } - nscoord maxStartBoxBSize = 0; - nscoord maxEndBoxBSize = 0; + nscoord maxTopBoxHeight = 0; + nscoord maxBottomBoxHeight = 0; PerFrameData* pfd = psd->mFirstFrame; while (nullptr != pfd) { nsIFrame* frame = pfd->mFrame; - WritingMode frameWM = frame->GetWritingMode(); // sanity check (see bug 105168, non-reproducible crashes from null frame) NS_ASSERTION(frame, "null frame in PerFrameData - something is very very bad"); @@ -1793,32 +1762,30 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) return; } - // Compute the logical block size of the frame - nscoord logicalBSize; + // Compute the logical height of the frame + nscoord logicalHeight; PerSpanData* frameSpan = pfd->mSpan; if (frameSpan) { - // For span frames the logical-block-size and start-leading were + // For span frames the logical-height and top-leading was // pre-computed when the span was reflowed. - logicalBSize = frameSpan->mLogicalBSize; + logicalHeight = frameSpan->mLogicalHeight; } else { - // For other elements the logical block size is the same as the - // frame's block size plus its margins. - logicalBSize = pfd->mBounds.BSize(lineWM) + - pfd->mMargin.BStartEnd(frameWM); - if (logicalBSize < 0 && + // For other elements the logical height is the same as the + // frames height plus its margins. + logicalHeight = pfd->mBounds.height + pfd->mMargin.TopBottom(); + if (logicalHeight < 0 && mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) { - pfd->mAscent -= logicalBSize; - logicalBSize = 0; + pfd->mAscent -= logicalHeight; + logicalHeight = 0; } } - // Get vertical-align property ("vertical-align" is the CSS name for - // block-direction align) + // Get vertical-align property const nsStyleCoord& verticalAlign = frame->StyleTextReset()->mVerticalAlign; uint8_t verticalAlignEnum = frame->VerticalAlignEnum(); -#ifdef NOISY_BLOCKDIR_ALIGN +#ifdef NOISY_VERTICAL_ALIGN printf(" [frame]"); nsFrame::ListTag(stdout, frame); printf(": verticalAlignUnit=%d (enum == %d", @@ -1840,8 +1807,8 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) { // The element's baseline is aligned with the baseline of // the parent. - pfd->mBounds.BStart(lineWM) = baselineBCoord - pfd->mAscent; - pfd->mBlockDirAlign = VALIGN_OTHER; + pfd->mBounds.y = baselineY - pfd->mAscent; + pfd->mVerticalAlign = VALIGN_OTHER; break; } @@ -1850,11 +1817,11 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // Lower the baseline of the box to the subscript offset // of the parent's box. This is identical to the baseline // alignment except for the addition of the subscript - // offset to the baseline BCoord. + // offset to the baseline Y. nscoord parentSubscript = fm->SubscriptOffset(); - nscoord revisedBaselineBCoord = baselineBCoord + parentSubscript; - pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord - pfd->mAscent; - pfd->mBlockDirAlign = VALIGN_OTHER; + nscoord revisedBaselineY = baselineY + parentSubscript; + pfd->mBounds.y = revisedBaselineY - pfd->mAscent; + pfd->mVerticalAlign = VALIGN_OTHER; break; } @@ -1863,40 +1830,40 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // Raise the baseline of the box to the superscript offset // of the parent's box. This is identical to the baseline // alignment except for the subtraction of the superscript - // offset to the baseline BCoord. + // offset to the baseline Y. nscoord parentSuperscript = fm->SuperscriptOffset(); - nscoord revisedBaselineBCoord = baselineBCoord - parentSuperscript; - pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord - pfd->mAscent; - pfd->mBlockDirAlign = VALIGN_OTHER; + nscoord revisedBaselineY = baselineY - parentSuperscript; + pfd->mBounds.y = revisedBaselineY - pfd->mAscent; + pfd->mVerticalAlign = VALIGN_OTHER; break; } case NS_STYLE_VERTICAL_ALIGN_TOP: { - pfd->mBlockDirAlign = VALIGN_TOP; - nscoord subtreeBSize = logicalBSize; + pfd->mVerticalAlign = VALIGN_TOP; + nscoord subtreeHeight = logicalHeight; if (frameSpan) { - subtreeBSize = frameSpan->mMaxBCoord - frameSpan->mMinBCoord; - NS_ASSERTION(subtreeBSize >= logicalBSize, - "unexpected subtree block size"); + subtreeHeight = frameSpan->mMaxY - frameSpan->mMinY; + NS_ASSERTION(subtreeHeight >= logicalHeight, + "unexpected subtree height"); } - if (subtreeBSize > maxStartBoxBSize) { - maxStartBoxBSize = subtreeBSize; + if (subtreeHeight > maxTopBoxHeight) { + maxTopBoxHeight = subtreeHeight; } break; } case NS_STYLE_VERTICAL_ALIGN_BOTTOM: { - pfd->mBlockDirAlign = VALIGN_BOTTOM; - nscoord subtreeBSize = logicalBSize; + pfd->mVerticalAlign = VALIGN_BOTTOM; + nscoord subtreeHeight = logicalHeight; if (frameSpan) { - subtreeBSize = frameSpan->mMaxBCoord - frameSpan->mMinBCoord; - NS_ASSERTION(subtreeBSize >= logicalBSize, - "unexpected subtree block size"); + subtreeHeight = frameSpan->mMaxY - frameSpan->mMinY; + NS_ASSERTION(subtreeHeight >= logicalHeight, + "unexpected subtree height"); } - if (subtreeBSize > maxEndBoxBSize) { - maxEndBoxBSize = subtreeBSize; + if (subtreeHeight > maxBottomBoxHeight) { + maxBottomBoxHeight = subtreeHeight; } break; } @@ -1907,15 +1874,14 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // x-height above the baseline. nscoord parentXHeight = fm->XHeight(); if (frameSpan) { - pfd->mBounds.BStart(lineWM) = baselineBCoord - - (parentXHeight + pfd->mBounds.BSize(lineWM))/2; + pfd->mBounds.y = baselineY - + (parentXHeight + pfd->mBounds.height)/2; } else { - pfd->mBounds.BStart(lineWM) = baselineBCoord - - (parentXHeight + logicalBSize)/2 + - pfd->mMargin.BStart(frameWM); + pfd->mBounds.y = baselineY - (parentXHeight + logicalHeight)/2 + + pfd->mMargin.top; } - pfd->mBlockDirAlign = VALIGN_OTHER; + pfd->mVerticalAlign = VALIGN_OTHER; break; } @@ -1925,14 +1891,13 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // the parent element's text. nscoord parentAscent = fm->MaxAscent(); if (frameSpan) { - pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent - - pfd->mBorderPadding.BStart(frameWM) + frameSpan->mBStartLeading; + pfd->mBounds.y = baselineY - parentAscent - + pfd->mBorderPadding.top + frameSpan->mTopLeading; } else { - pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent + - pfd->mMargin.BStart(frameWM); + pfd->mBounds.y = baselineY - parentAscent + pfd->mMargin.top; } - pfd->mBlockDirAlign = VALIGN_OTHER; + pfd->mVerticalAlign = VALIGN_OTHER; break; } @@ -1942,17 +1907,15 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // bottom of the parent elements text. nscoord parentDescent = fm->MaxDescent(); if (frameSpan) { - pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent - - pfd->mBounds.BStart(lineWM) + - pfd->mBorderPadding.BEnd(frameWM) - - frameSpan->mBEndLeading; + pfd->mBounds.y = baselineY + parentDescent - + pfd->mBounds.height + pfd->mBorderPadding.bottom - + frameSpan->mBottomLeading; } else { - pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent - - pfd->mBounds.BSize(lineWM) - - pfd->mMargin.BEnd(frameWM); + pfd->mBounds.y = baselineY + parentDescent - + pfd->mBounds.height - pfd->mMargin.bottom; } - pfd->mBlockDirAlign = VALIGN_OTHER; + pfd->mVerticalAlign = VALIGN_OTHER; break; } @@ -1960,14 +1923,12 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) { // Align the midpoint of the frame with the baseline of the parent. if (frameSpan) { - pfd->mBounds.BStart(lineWM) = baselineBCoord - - pfd->mBounds.BSize(lineWM)/2; + pfd->mBounds.y = baselineY - pfd->mBounds.height/2; } else { - pfd->mBounds.BStart(lineWM) = baselineBCoord - logicalBSize/2 + - pfd->mMargin.BStart(frameWM); + pfd->mBounds.y = baselineY - logicalHeight/2 + pfd->mMargin.top; } - pfd->mBlockDirAlign = VALIGN_OTHER; + pfd->mVerticalAlign = VALIGN_OTHER; break; } } @@ -1976,11 +1937,11 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) nscoord pctBasis = 0; if (verticalAlign.HasPercent()) { // Percentages are like lengths, except treated as a percentage - // of the elements line block size value. + // of the elements line-height value. float inflation = - GetInflationForBlockDirAlignment(frame, mInflationMinFontSize); + GetInflationForVerticalAlignment(frame, mInflationMinFontSize); pctBasis = nsHTMLReflowState::CalcLineHeight( - frame->StyleContext(), mBlockReflowState->ComputedBSize(), + frame->StyleContext(), mBlockReflowState->ComputedHeight(), inflation); } nscoord offset = @@ -1990,14 +1951,14 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // "lowers" the box by the given distance (with zero being the // baseline). Since Y coordinates increase towards the bottom of // the screen we reverse the sign. - nscoord revisedBaselineBCoord = baselineBCoord - offset; - pfd->mBounds.BStart(lineWM) = revisedBaselineBCoord - pfd->mAscent; - pfd->mBlockDirAlign = VALIGN_OTHER; + nscoord revisedBaselineY = baselineY - offset; + pfd->mBounds.y = revisedBaselineY - pfd->mAscent; + pfd->mVerticalAlign = VALIGN_OTHER; } - // Update minBCoord/maxBCoord for frames that we just placed. Do not factor + // Update minY/maxY for frames that we just placed. Do not factor // text into the equation. - if (pfd->mBlockDirAlign == VALIGN_OTHER) { + if (pfd->mVerticalAlign == VALIGN_OTHER) { // Text frames and bullets do not contribute to the min/max Y values for // the line (instead their parent frame's font-size contributes). // XXXrbs -- relax this restriction because it causes text frames @@ -2019,50 +1980,48 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) frame->StyleText()->mLineHeight.GetUnit() == eStyleUnit_Normal; } if (canUpdate) { - nscoord blockStart, blockEnd; + nscoord yTop, yBottom; if (frameSpan) { // For spans that were are now placing, use their position // plus their already computed min-Y and max-Y values for - // computing blockStart and blockEnd. - blockStart = pfd->mBounds.BStart(lineWM) + frameSpan->mMinBCoord; - blockEnd = pfd->mBounds.BStart(lineWM) + frameSpan->mMaxBCoord; + // computing yTop and yBottom. + yTop = pfd->mBounds.y + frameSpan->mMinY; + yBottom = pfd->mBounds.y + frameSpan->mMaxY; } else { - blockStart = pfd->mBounds.BStart(lineWM) - - pfd->mMargin.BStart(frameWM); - blockEnd = blockStart + logicalBSize; + yTop = pfd->mBounds.y - pfd->mMargin.top; + yBottom = yTop + logicalHeight; } if (!preMode && mPresContext->CompatibilityMode() != eCompatibility_FullStandards && - !logicalBSize) { + !logicalHeight) { // Check if it's a BR frame that is not alone on its line (it - // is given a block size of zero to indicate this), and if so reset - // blockStart and blockEnd so that BR frames don't influence the line. + // is given a height of zero to indicate this), and if so reset + // yTop and yBottom so that BR frames don't influence the line. if (nsGkAtoms::brFrame == frame->GetType()) { - blockStart = BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM; - blockEnd = BLOCKDIR_ALIGN_FRAMES_NO_MAXIMUM; + yTop = VERTICAL_ALIGN_FRAMES_NO_MINIMUM; + yBottom = VERTICAL_ALIGN_FRAMES_NO_MAXIMUM; } } - if (blockStart < minBCoord) minBCoord = blockStart; - if (blockEnd > maxBCoord) maxBCoord = blockEnd; -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" [frame]raw: a=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minBCoord=%d maxBCoord=%d\n", - pfd->mAscent, pfd->mBounds.BSize(lineWM), - pfd->mBorderPadding.Top(frameWM), - pfd->mBorderPadding.Bottom(frameWM), - logicalBSize, - frameSpan ? frameSpan->mBStartLeading : 0, - pfd->mBounds.BStart(lineWM), minBCoord, maxBCoord); + if (yTop < minY) minY = yTop; + if (yBottom > maxY) maxY = yBottom; +#ifdef NOISY_VERTICAL_ALIGN + printf(" [frame]raw: a=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minY=%d maxY=%d\n", + pfd->mAscent, pfd->mBounds.height, + pfd->mBorderPadding.top, pfd->mBorderPadding.bottom, + logicalHeight, + frameSpan ? frameSpan->mTopLeading : 0, + pfd->mBounds.y, minY, maxY); #endif } if (psd != mRootSpan) { - frame->SetRect(lineWM, pfd->mBounds, mContainerWidth); + frame->SetRect(pfd->mBounds); } } pfd = pfd->mNext; } - // Factor in the minimum line block-size when handling the root-span for + // Factor in the minimum line-height when handling the root-span for // the block. if (psd == mRootSpan) { // We should factor in the block element's minimum line-height (as @@ -2093,22 +2052,22 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) } if (applyMinLH) { if (psd->mHasNonemptyContent || preMode || mHasBullet) { -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" [span]==> adjusting min/maxBCoord: currentValues: %d,%d", minBCoord, maxBCoord); +#ifdef NOISY_VERTICAL_ALIGN + printf(" [span]==> adjusting min/maxY: currentValues: %d,%d", minY, maxY); #endif - nscoord minimumLineBSize = mMinLineBSize; - nscoord blockStart = - -nsLayoutUtils::GetCenteredFontBaseline(fm, minimumLineBSize); - nscoord blockEnd = blockStart + minimumLineBSize; + nscoord minimumLineHeight = mMinLineHeight; + nscoord yTop = + -nsLayoutUtils::GetCenteredFontBaseline(fm, minimumLineHeight); + nscoord yBottom = yTop + minimumLineHeight; - if (blockStart < minBCoord) minBCoord = blockStart; - if (blockEnd > maxBCoord) maxBCoord = blockEnd; + if (yTop < minY) minY = yTop; + if (yBottom > maxY) maxY = yBottom; -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" new values: %d,%d\n", minBCoord, maxBCoord); +#ifdef NOISY_VERTICAL_ALIGN + printf(" new values: %d,%d\n", minY, maxY); #endif -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" Used mMinLineBSize: %d, blockStart: %d, blockEnd: %d\n", mMinLineBSize, blockStart, blockEnd); +#ifdef NOISY_VERTICAL_ALIGN + printf(" Used mMinLineHeight: %d, yTop: %d, yBottom: %d\n", mMinLineHeight, yTop, yBottom); #endif } else { @@ -2118,34 +2077,33 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // [3] blank lines in a pre-section ("\n") (handled with preMode) // XXX Are there other problems with this? -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" [span]==> zapping min/maxBCoord: currentValues: %d,%d newValues: 0,0\n", - minBCoord, maxBCoord); +#ifdef NOISY_VERTICAL_ALIGN + printf(" [span]==> zapping min/maxY: currentValues: %d,%d newValues: 0,0\n", + minY, maxY); #endif - minBCoord = maxBCoord = 0; + minY = maxY = 0; } } } - if ((minBCoord == BLOCKDIR_ALIGN_FRAMES_NO_MINIMUM) || - (maxBCoord == BLOCKDIR_ALIGN_FRAMES_NO_MAXIMUM)) { - minBCoord = maxBCoord = baselineBCoord; + if ((minY == VERTICAL_ALIGN_FRAMES_NO_MINIMUM) || + (maxY == VERTICAL_ALIGN_FRAMES_NO_MAXIMUM)) { + minY = maxY = baselineY; } if ((psd != mRootSpan) && (psd->mZeroEffectiveSpanBox)) { -#ifdef NOISY_BLOCKDIR_ALIGN +#ifdef NOISY_VERTICAL_ALIGN printf(" [span]adjusting for zeroEffectiveSpanBox\n"); - printf(" Original: minBCoord=%d, maxBCoord=%d, bSize=%d, ascent=%d, logicalBSize=%d, topLeading=%d, bottomLeading=%d\n", - minBCoord, maxBCoord, spanFramePFD->mBounds.BSize(frameWM), + printf(" Original: minY=%d, maxY=%d, height=%d, ascent=%d, logicalHeight=%d, topLeading=%d, bottomLeading=%d\n", + minY, maxY, spanFramePFD->mBounds.height, spanFramePFD->mAscent, - psd->mLogicalBSize, psd->mBStartLeading, psd->mBEndLeading); + psd->mLogicalHeight, psd->mTopLeading, psd->mBottomLeading); #endif - nscoord goodMinBCoord = spanFramePFD->mBorderPadding.BStart(frameWM) - - psd->mBStartLeading; - nscoord goodMaxBCoord = goodMinBCoord + psd->mLogicalBSize; + nscoord goodMinY = spanFramePFD->mBorderPadding.top - psd->mTopLeading; + nscoord goodMaxY = goodMinY + psd->mLogicalHeight; // For cases like the one in bug 714519 (text-decoration placement - // or making nsLineLayout::IsZeroBSize() handle + // or making nsLineLayout::IsZeroHeight() handle // vertical-align:top/bottom on a descendant of the line that's not // a child of it), we want to treat elements that are // vertical-align: top or bottom somewhat like children for the @@ -2155,100 +2113,98 @@ nsLineLayout::BlockDirAlignFrames(PerSpanData* psd) // frame (as though this frame is the only thing in the line). // (Guessing isn't crazy, since all we're doing is reducing the // scope of a quirk and making the behavior more standards-like.) - if (maxStartBoxBSize > maxBCoord - minBCoord) { - // Distribute maxStartBoxBSize to ascent (baselineBCoord - minBCoord), and - // then to descent (maxBCoord - baselineBCoord) by adjusting minBCoord or - // maxBCoord, but not to exceed goodMinBCoord and goodMaxBCoord. - nscoord distribute = maxStartBoxBSize - (maxBCoord - minBCoord); - nscoord ascentSpace = std::max(minBCoord - goodMinBCoord, 0); + if (maxTopBoxHeight > maxY - minY) { + // Distribute maxTopBoxHeight to ascent (baselineY - minY), and + // then to descent (maxY - baselineY) by adjusting minY or maxY, + // but not to exceed goodMinY and goodMaxY. + nscoord distribute = maxTopBoxHeight - (maxY - minY); + nscoord ascentSpace = std::max(minY - goodMinY, 0); if (distribute > ascentSpace) { distribute -= ascentSpace; - minBCoord -= ascentSpace; - nscoord descentSpace = std::max(goodMaxBCoord - maxBCoord, 0); + minY -= ascentSpace; + nscoord descentSpace = std::max(goodMaxY - maxY, 0); if (distribute > descentSpace) { - maxBCoord += descentSpace; + maxY += descentSpace; } else { - maxBCoord += distribute; + maxY += distribute; } } else { - minBCoord -= distribute; + minY -= distribute; } } - if (maxEndBoxBSize > maxBCoord - minBCoord) { + if (maxBottomBoxHeight > maxY - minY) { // Likewise, but preferring descent to ascent. - nscoord distribute = maxEndBoxBSize - (maxBCoord - minBCoord); - nscoord descentSpace = std::max(goodMaxBCoord - maxBCoord, 0); + nscoord distribute = maxBottomBoxHeight - (maxY - minY); + nscoord descentSpace = std::max(goodMaxY - maxY, 0); if (distribute > descentSpace) { distribute -= descentSpace; - maxBCoord += descentSpace; - nscoord ascentSpace = std::max(minBCoord - goodMinBCoord, 0); + maxY += descentSpace; + nscoord ascentSpace = std::max(minY - goodMinY, 0); if (distribute > ascentSpace) { - minBCoord -= ascentSpace; + minY -= ascentSpace; } else { - minBCoord -= distribute; + minY -= distribute; } } else { - maxBCoord += distribute; + maxY += distribute; } } - if (minBCoord > goodMinBCoord) { - nscoord adjust = minBCoord - goodMinBCoord; // positive + if (minY > goodMinY) { + nscoord adjust = minY - goodMinY; // positive // shrink the logical extents - psd->mLogicalBSize -= adjust; - psd->mBStartLeading -= adjust; + psd->mLogicalHeight -= adjust; + psd->mTopLeading -= adjust; } - if (maxBCoord < goodMaxBCoord) { - nscoord adjust = goodMaxBCoord - maxBCoord; - psd->mLogicalBSize -= adjust; - psd->mBEndLeading -= adjust; + if (maxY < goodMaxY) { + nscoord adjust = goodMaxY - maxY; + psd->mLogicalHeight -= adjust; + psd->mBottomLeading -= adjust; } - if (minBCoord > 0) { + if (minY > 0) { - // shrink the content by moving its block start down. This is tricky, - // since the block start is the 0 for many coordinates, so what we do is + // shrink the content by moving its top down. This is tricky, since + // the top is the 0 for many coordinates, so what we do is // move everything else up. - spanFramePFD->mAscent -= minBCoord; // move the baseline up - spanFramePFD->mBounds.BSize(lineWM) -= minBCoord; // move the block end up - psd->mBStartLeading += minBCoord; - *psd->mBaseline -= minBCoord; + spanFramePFD->mAscent -= minY; // move the baseline up + spanFramePFD->mBounds.height -= minY; // move the bottom up + psd->mTopLeading += minY; + *psd->mBaseline -= minY; pfd = psd->mFirstFrame; while (nullptr != pfd) { - pfd->mBounds.BStart(lineWM) -= minBCoord; // move all the children - // back up - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); + pfd->mBounds.y -= minY; // move all the children back up + pfd->mFrame->SetRect(pfd->mBounds); pfd = pfd->mNext; } - maxBCoord -= minBCoord; // since minBCoord is in the frame's own - // coordinate system - minBCoord = 0; + maxY -= minY; // since minY is in the frame's own coordinate system + minY = 0; } - if (maxBCoord < spanFramePFD->mBounds.BSize(lineWM)) { - nscoord adjust = spanFramePFD->mBounds.BSize(lineWM) - maxBCoord; - spanFramePFD->mBounds.BSize(lineWM) -= adjust; // move the bottom up - psd->mBEndLeading += adjust; + if (maxY < spanFramePFD->mBounds.height) { + nscoord adjust = spanFramePFD->mBounds.height - maxY; + spanFramePFD->mBounds.height -= adjust; // move the bottom up + psd->mBottomLeading += adjust; } -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" New: minBCoord=%d, maxBCoord=%d, bSize=%d, ascent=%d, logicalBSize=%d, topLeading=%d, bottomLeading=%d\n", - minBCoord, maxBCoord, spanFramePFD->mBounds.BSize(lineWM), +#ifdef NOISY_VERTICAL_ALIGN + printf(" New: minY=%d, maxY=%d, height=%d, ascent=%d, logicalHeight=%d, topLeading=%d, bottomLeading=%d\n", + minY, maxY, spanFramePFD->mBounds.height, spanFramePFD->mAscent, - psd->mLogicalBSize, psd->mBStartLeading, psd->mBEndLeading); + psd->mLogicalHeight, psd->mTopLeading, psd->mBottomLeading); #endif } - psd->mMinBCoord = minBCoord; - psd->mMaxBCoord = maxBCoord; -#ifdef NOISY_BLOCKDIR_ALIGN - printf(" [span]==> minBCoord=%d maxBCoord=%d delta=%d maxStartBoxBSize=%d maxEndBoxBSize=%d\n", - minBCoord, maxBCoord, maxBCoord - minBCoord, maxStartBoxBSize, maxEndBoxBSize); + psd->mMinY = minY; + psd->mMaxY = maxY; +#ifdef NOISY_VERTICAL_ALIGN + printf(" [span]==> minY=%d maxY=%d delta=%d maxTopBoxHeight=%d maxBottomBoxHeight=%d\n", + minY, maxY, maxY - minY, maxTopBoxHeight, maxBottomBoxHeight); #endif - if (maxStartBoxBSize > mMaxStartBoxBSize) { - mMaxStartBoxBSize = maxStartBoxBSize; + if (maxTopBoxHeight > mMaxTopBoxHeight) { + mMaxTopBoxHeight = maxTopBoxHeight; } - if (maxEndBoxBSize > mMaxEndBoxBSize) { - mMaxEndBoxBSize = maxEndBoxBSize; + if (maxBottomBoxHeight > mMaxBottomBoxHeight) { + mMaxBottomBoxHeight = maxBottomBoxHeight; } } @@ -2265,11 +2221,19 @@ static void SlideSpanFrameRect(nsIFrame* aFrame, nscoord aDeltaWidth) bool nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd, - nscoord* aDeltaISize) + nscoord* aDeltaWidth) { +#ifndef IBMBIDI +// XXX what about NS_STYLE_DIRECTION_RTL? + if (NS_STYLE_DIRECTION_RTL == psd->mDirection) { + *aDeltaWidth = 0; + return true; + } +#endif + PerFrameData* pfd = psd->mFirstFrame; if (!pfd) { - *aDeltaISize = 0; + *aDeltaWidth = 0; return false; } pfd = pfd->Last(); @@ -2283,45 +2247,44 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd, printf("\n"); #endif PerSpanData* childSpan = pfd->mSpan; - WritingMode lineWM = mRootSpan->mWritingMode; if (childSpan) { // Maybe the child span has the trailing white-space in it? - if (TrimTrailingWhiteSpaceIn(childSpan, aDeltaISize)) { - nscoord deltaISize = *aDeltaISize; - if (deltaISize) { + if (TrimTrailingWhiteSpaceIn(childSpan, aDeltaWidth)) { + nscoord deltaWidth = *aDeltaWidth; + if (deltaWidth) { // Adjust the child spans frame size - pfd->mBounds.ISize(lineWM) -= deltaISize; + pfd->mBounds.width -= deltaWidth; if (psd != mRootSpan) { // When the child span is not a direct child of the block // we need to update the child spans frame rectangle // because it most likely will not be done again. Spans // that are direct children of the block will be updated - // later, however, because the BlockDirAlignFrames method + // later, however, because the VerticalAlignFrames method // will be run after this method. nsIFrame* f = pfd->mFrame; - LogicalRect r(lineWM, f->GetRect(), mContainerWidth); - r.ISize(lineWM) -= deltaISize; - f->SetRect(lineWM, r, mContainerWidth); + nsRect r = f->GetRect(); + r.width -= deltaWidth; + f->SetRect(r); } - // Adjust the inline end edge of the span that contains the child span - psd->mICoord -= deltaISize; + // Adjust the right edge of the span that contains the child span + psd->mX -= deltaWidth; // Slide any frames that follow the child span over by the - // correct amount. The only thing that can follow the child + // right amount. The only thing that can follow the child // span is empty stuff, so we are just making things // sensible (keeping the combined area honest). while (pfd->mNext) { pfd = pfd->mNext; - pfd->mBounds.IStart(lineWM) -= deltaISize; + pfd->mBounds.x -= deltaWidth; if (psd != mRootSpan) { // When the child span is not a direct child of the block - // we need to update the child span's frame rectangle + // we need to update the child spans frame rectangle // because it most likely will not be done again. Spans // that are direct children of the block will be updated - // later, however, because the BlockDirAlignFrames method + // later, however, because the VerticalAlignFrames method // will be run after this method. - SlideSpanFrameRect(pfd->mFrame, deltaISize); + SlideSpanFrameRect(pfd->mFrame, deltaWidth); } } } @@ -2332,7 +2295,7 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd, !pfd->GetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE)) { // If we hit a frame on the end that's not text and not a placeholder, // then there is no trailing whitespace to trim. Stop the search. - *aDeltaISize = 0; + *aDeltaWidth = 0; return true; } else if (pfd->GetFlag(PFD_ISTEXTFRAME)) { @@ -2358,17 +2321,17 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd, } if (trimOutput.mDeltaWidth) { - pfd->mBounds.ISize(lineWM) -= trimOutput.mDeltaWidth; + pfd->mBounds.width -= trimOutput.mDeltaWidth; // See if the text frame has already been placed in its parent if (psd != mRootSpan) { // The frame was already placed during psd's // reflow. Update the frames rectangle now. - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); + pfd->mFrame->SetRect(pfd->mBounds); } // Adjust containing span's right edge - psd->mICoord -= trimOutput.mDeltaWidth; + psd->mX -= trimOutput.mDeltaWidth; // Slide any frames that follow the text frame over by the // right amount. The only thing that can follow the text @@ -2376,13 +2339,13 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd, // sensible (keeping the combined area honest). while (pfd->mNext) { pfd = pfd->mNext; - pfd->mBounds.IStart(lineWM) -= trimOutput.mDeltaWidth; + pfd->mBounds.x -= trimOutput.mDeltaWidth; if (psd != mRootSpan) { // When the child span is not a direct child of the block // we need to update the child spans frame rectangle // because it most likely will not be done again. Spans // that are direct children of the block will be updated - // later, however, because the BlockDirAlignFrames method + // later, however, because the VerticalAlignFrames method // will be run after this method. SlideSpanFrameRect(pfd->mFrame, trimOutput.mDeltaWidth); } @@ -2391,14 +2354,14 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd, if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME) || trimOutput.mChanged) { // Pass up to caller so they can shrink their span - *aDeltaISize = trimOutput.mDeltaWidth; + *aDeltaWidth = trimOutput.mDeltaWidth; return true; } } pfd = pfd->mPrev; } - *aDeltaISize = 0; + *aDeltaWidth = 0; return false; } @@ -2406,9 +2369,9 @@ bool nsLineLayout::TrimTrailingWhiteSpace() { PerSpanData* psd = mRootSpan; - nscoord deltaISize; - TrimTrailingWhiteSpaceIn(psd, &deltaISize); - return 0 != deltaISize; + nscoord deltaWidth; + TrimTrailingWhiteSpaceIn(psd, &deltaWidth); + return 0 != deltaWidth; } void @@ -2449,15 +2412,14 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState NS_ASSERTION(aPSD, "null arg"); NS_ASSERTION(aState, "null arg"); - nscoord deltaICoord = 0; + nscoord deltaX = 0; for (PerFrameData* pfd = aPSD->mFirstFrame; pfd != nullptr; pfd = pfd->mNext) { // Don't reposition bullets (and other frames that occur out of X-order?) if (!pfd->GetFlag(PFD_ISBULLET)) { nscoord dw = 0; - WritingMode lineWM = aPSD->mWritingMode; - - pfd->mBounds.IStart(lineWM) += deltaICoord; - + + pfd->mBounds.x += deltaX; + if (true == pfd->GetFlag(PFD_ISTEXTFRAME)) { if (aState->mTotalWidthForSpaces > 0 && aState->mTotalNumSpaces > 0) { @@ -2494,40 +2456,37 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState dw += ApplyFrameJustification(pfd->mSpan, aState); } } + + pfd->mBounds.width += dw; - pfd->mBounds.ISize(lineWM) += dw; - - deltaICoord += dw; - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); + deltaX += dw; + pfd->mFrame->SetRect(pfd->mBounds); } } - return deltaICoord; + return deltaX; } void -nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds, - bool aIsLastLine, - int32_t aFrameCount) +nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds, + 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; - NS_WARN_IF_FALSE(psd->mIEnd != NS_UNCONSTRAINEDSIZE, + NS_WARN_IF_FALSE(psd->mRightEdge != 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 availWidth = psd->mRightEdge - psd->mLeftEdge; nscoord remainingWidth = availWidth - aLineBounds.width; -#ifdef NOISY_INLINEDIR_ALIGN +#ifdef NOISY_HORIZONTAL_ALIGN nsFrame::ListTag(stdout, mBlockReflowState->frame); - printf(": availWidth=%d lineBounds.x=%d lineWidth=%d delta=%d\n", - availWidth, aLineBounds.x, aLineBounds.width, remainingWidth); + printf(": availWidth=%d lineWidth=%d delta=%d\n", + availWidth, aLineBounds.width, remainingWidth); #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. @@ -2572,27 +2531,30 @@ nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds, // the space. case NS_STYLE_TEXT_ALIGN_DEFAULT: - // default alignment is to start edge so do nothing - break; - - case NS_STYLE_TEXT_ALIGN_LEFT: - case NS_STYLE_TEXT_ALIGN_MOZ_LEFT: - if (!lineWM.IsBidiLTR()) { - dx = remainingWidth; + if (NS_STYLE_DIRECTION_LTR == psd->mDirection) { + // default alignment for left-to-right is left so do nothing + break; } - break; + // Fall through to align right case for default alignment + // used when the direction is right-to-left. case NS_STYLE_TEXT_ALIGN_RIGHT: case NS_STYLE_TEXT_ALIGN_MOZ_RIGHT: - if (lineWM.IsBidiLTR()) { - dx = remainingWidth; - } - break; - - case NS_STYLE_TEXT_ALIGN_END: dx = remainingWidth; break; + case NS_STYLE_TEXT_ALIGN_END: + if (NS_STYLE_DIRECTION_LTR == psd->mDirection) { + // Do what we do for ALIGN_RIGHT + dx = remainingWidth; + break; + } + // Fall through to align left case for end alignment + // used when the direction is right-to-left. + + case NS_STYLE_TEXT_ALIGN_LEFT: + case NS_STYLE_TEXT_ALIGN_MOZ_LEFT: + break; case NS_STYLE_TEXT_ALIGN_CENTER: case NS_STYLE_TEXT_ALIGN_MOZ_CENTER: @@ -2600,20 +2562,31 @@ nsLineLayout::InlineDirAlignFrames(nsRect& aLineBounds, break; } } + else if (remainingWidth < 0 || textAlignTrue) { + if (NS_STYLE_DIRECTION_RTL == psd->mDirection) { + dx = remainingWidth; + psd->mX += dx; + psd->mLeftEdge += dx; + } + } + + if (NS_STYLE_DIRECTION_RTL == psd->mDirection && + !psd->mChangedFrameDirection) { + if (psd->mLastFrame->GetFlag(PFD_ISBULLET) ) { + PerFrameData* bulletPfd = psd->mLastFrame; + bulletPfd->mBounds.x -= remainingWidth; + bulletPfd->mFrame->SetRect(bulletPfd->mBounds); + } + psd->mChangedFrameDirection = true; + } if (dx) { for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) { - pfd->mBounds.IStart(lineWM) += dx; - pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth); + pfd->mBounds.x += dx; + pfd->mFrame->SetRect(pfd->mBounds); } aLineBounds.x += dx; } - - if (mPresContext->BidiEnabled() && - (!mPresContext->IsVisualMode() || !lineWM.IsBidiLTR())) { - nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame, aFrameCount, - lineWM, mContainerWidth); - } } void @@ -2626,7 +2599,6 @@ void nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflowAreas) { nsOverflowAreas overflowAreas; - WritingMode wm = psd->mWritingMode; if (nullptr != psd->mFrame) { // The span's overflow areas come in three parts: // -- this frame's width and height @@ -2646,13 +2618,18 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflo psd->mFrame->mOverflowAreas.VisualOverflow(), adjustedBounds); } else { - LogicalRect rect(wm, psd->mIStart, mBStartEdge, - psd->mICoord - psd->mIStart, mFinalLineBSize); // The minimum combined area for the frames that are direct // children of the block starts at the upper left corner of the // line and is sized to match the size of the line's bounding box - // (the same size as the values returned from BlockDirAlignFrames) - overflowAreas.VisualOverflow() = rect.GetPhysicalRect(wm, mContainerWidth); + // (the same size as the values returned from VerticalAlignFrames) + overflowAreas.VisualOverflow().x = psd->mLeftEdge; + // If this turns out to be negative, the rect will be treated as empty. + // Which is just fine. + overflowAreas.VisualOverflow().width = + psd->mX - overflowAreas.VisualOverflow().x; + overflowAreas.VisualOverflow().y = mTopEdge; + overflowAreas.VisualOverflow().height = mFinalLineHeight; + overflowAreas.ScrollableOverflow() = overflowAreas.VisualOverflow(); } @@ -2662,13 +2639,10 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflo // Adjust the origin of the frame if (pfd->GetFlag(PFD_RELATIVEPOS)) { - //XXX temporary until ApplyRelativePositioning can handle logical offsets - nsMargin physicalOffsets = - pfd->mOffsets.GetPhysicalMargin(pfd->mFrame->GetWritingMode()); // right and bottom are handled by // nsHTMLReflowState::ComputeRelativeOffsets nsHTMLReflowState::ApplyRelativePositioning(pfd->mFrame, - physicalOffsets, + pfd->mOffsets, &origin); frame->SetPosition(origin); } @@ -2696,7 +2670,7 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflo // We need to recompute overflow areas in two cases: // (1) When PFD_RECOMPUTEOVERFLOW is set due to trimming // (2) When there are text decorations, since we can't recompute the - // overflow area until Reflow and BlockDirAlignLine have finished + // overflow area until Reflow and VerticalAlignLine have finished if (pfd->GetFlag(PFD_RECOMPUTEOVERFLOW) || frame->StyleContext()->HasTextDecorationLines()) { nsTextFrame* f = static_cast(frame); diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index 7fbe92167839..0d8c1e2fea67 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -21,7 +21,6 @@ #include "nsBlockReflowState.h" #include "plarena.h" #include "gfxTypes.h" -#include "WritingModes.h" class nsFloatManager; struct nsStyleText; @@ -34,10 +33,10 @@ public: const nsLineList::iterator* aLine); ~nsLineLayout(); - void Init(nsBlockReflowState* aState, nscoord aMinLineBSize, + void Init(nsBlockReflowState* aState, nscoord aMinLineHeight, int32_t aLineNumber) { mBlockRS = aState; - mMinLineBSize = aMinLineBSize; + mMinLineHeight = aMinLineHeight; mLineNumber = aLineNumber; } @@ -45,12 +44,11 @@ public: return mLineNumber; } - void BeginLineReflow(nscoord aICoord, nscoord aBCoord, - nscoord aISize, nscoord aBSize, + void BeginLineReflow(nscoord aX, nscoord aY, + nscoord aWidth, nscoord aHeight, bool aImpactedByFloats, bool aIsTopOfPage, - mozilla::WritingMode aWritingMode, - nscoord aContainerWidth); + uint8_t aDirection); void EndLineReflow(); @@ -75,7 +73,7 @@ public: void SplitLineTo(int32_t aNewCount); - bool IsZeroBSize(); + bool IsZeroHeight(); // Reflows the frame and returns the reflow status. aPushedFrame is true // if the frame is pushed to the next line because it doesn't fit @@ -90,12 +88,11 @@ public: PushFrame(aFrame); } - void BlockDirAlignLine(); + void VerticalAlignLine(); bool TrimTrailingWhiteSpace(); - void InlineDirAlignFrames(nsRect& aLineBounds, bool aIsLastLine, - int32_t aFrameCount); + void HorizontalAlignFrames(nsRect& aLineBounds, bool aIsLastLine); /** * Handle all the relative positioning in the line, compute the @@ -306,10 +303,10 @@ public: * the right edge for RTL blocks and from the left edge for LTR blocks. * In other words, the current frame's distance from the line container's * start content edge is: - * GetCurrentFrameInlineDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left + * GetCurrentFrameXDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left * Note the use of .left for both LTR and RTL line containers. */ - nscoord GetCurrentFrameInlineDistanceFromBlock(); + nscoord GetCurrentFrameXDistanceFromBlock(); protected: // This state is constant for a given block frame doing line layout @@ -329,22 +326,14 @@ protected: // Per-frame data recorded by the line-layout reflow logic. This // state is the state needed to post-process the line after reflow - // has completed (block-direction alignment, inline-direction alignment, + // has completed (vertical alignment, horizontal alignment, // justification and relative positioning). struct PerSpanData; struct PerFrameData; friend struct PerSpanData; friend struct PerFrameData; - struct PerFrameData - { - PerFrameData(mozilla::WritingMode aWritingMode) - : mBounds(aWritingMode) - , mMargin(aWritingMode) - , mBorderPadding(aWritingMode) - , mOffsets(aWritingMode) - {} - + struct PerFrameData { // link to next/prev frame in same span PerFrameData* mNext; PerFrameData* mPrev; @@ -357,23 +346,20 @@ protected: // From metrics nscoord mAscent; - // note that mBounds is a logical rect in the *line*'s writing mode. - // When setting frame coordinates, we have to convert to the frame's - // writing mode - mozilla::LogicalRect mBounds; + nsRect mBounds; nsOverflowAreas mOverflowAreas; // From reflow-state - mozilla::LogicalMargin mMargin; - mozilla::LogicalMargin mBorderPadding; - mozilla::LogicalMargin mOffsets; + nsMargin mMargin; + nsMargin mBorderPadding; + nsMargin mOffsets; // state for text justification int32_t mJustificationNumSpaces; int32_t mJustificationNumLetters; // Other state we use - uint8_t mBlockDirAlign; + uint8_t mVerticalAlign; // PerFrameData flags #define PFD_RELATIVEPOS 0x00000001 @@ -428,18 +414,19 @@ protected: const nsHTMLReflowState* mReflowState; bool mNoWrap; - mozilla::WritingMode mWritingMode; + uint8_t mDirection; + bool mChangedFrameDirection; bool mZeroEffectiveSpanBox; bool mContainsFloat; bool mHasNonemptyContent; - nscoord mIStart; - nscoord mICoord; - nscoord mIEnd; + nscoord mLeftEdge; + nscoord mX; + nscoord mRightEdge; - nscoord mBStartLeading, mBEndLeading; - nscoord mLogicalBSize; - nscoord mMinBCoord, mMaxBCoord; + nscoord mTopLeading, mBottomLeading; + nscoord mLogicalHeight; + nscoord mMinY, mMaxY; nscoord* mBaseline; void AppendFrame(PerFrameData* pfd) { @@ -461,7 +448,7 @@ protected: int32_t mLastOptionalBreakContentOffset; int32_t mForceBreakContentOffset; - nscoord mMinLineBSize; + nscoord mMinLineHeight; // The amount of text indent that we applied to this line, needed for // max-element-size calculation. @@ -475,21 +462,19 @@ protected: int32_t mTotalPlacedFrames; - nscoord mBStartEdge; - nscoord mMaxStartBoxBSize; - nscoord mMaxEndBoxBSize; + nscoord mTopEdge; + nscoord mMaxTopBoxHeight; + nscoord mMaxBottomBoxHeight; nscoord mInflationMinFontSize; - // Final computed line-bSize value after BlockDirAlignFrames for + // Final computed line-height value after VerticalAlignFrames for // the block has been called. - nscoord mFinalLineBSize; + nscoord mFinalLineHeight; // Amount of trimmable whitespace width for the trailing text frame, if any nscoord mTrimmableWidth; - nscoord mContainerWidth; - bool mFirstLetterStyleOK : 1; bool mIsTopOfPage : 1; bool mImpactedByFloats : 1; @@ -514,7 +499,7 @@ protected: /** * Allocate a PerFrameData from the mArena pool. The allocation is infallible. */ - PerFrameData* NewPerFrameData(nsIFrame* aFrame); + PerFrameData* NewPerFrameData(); /** * Allocate a PerSpanData from the mArena pool. The allocation is infallible. @@ -533,6 +518,7 @@ protected: nsHTMLReflowState& aReflowState); bool CanPlaceFrame(PerFrameData* pfd, + uint8_t aFrameDirection, bool aNotSafeToBreak, bool aFrameCanContinueTextRun, bool aCanRollBackBeforeFrame, @@ -543,15 +529,15 @@ protected: void PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics); - void BlockDirAlignFrames(PerSpanData* psd); + void VerticalAlignFrames(PerSpanData* psd); - void PlaceStartEndFrames(PerSpanData* psd, - nscoord aDistanceFromStart, - nscoord aLineBSize); + void PlaceTopBottomFrames(PerSpanData* psd, + nscoord aDistanceFromTop, + nscoord aLineHeight); void RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflowAreas); - bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaISize); + bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth); void ComputeJustificationWeights(PerSpanData* psd, int32_t* numSpaces, int32_t* numLetters); diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 1a1213736a6f..eb5f0b283b18 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -7841,7 +7841,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, iter.SetOriginalOffset(offset); nscoord xOffsetForTabs = (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TAB) ? - (aLineLayout.GetCurrentFrameInlineDistanceFromBlock() - + (aLineLayout.GetCurrentFrameXDistanceFromBlock() - lineContainer->GetUsedBorderAndPadding().left) : -1; PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length,