nsLineLayout.h (25877B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* state and methods used while laying out a single line of a block frame */ 8 9 #ifndef nsLineLayout_h___ 10 #define nsLineLayout_h___ 11 12 #include "BlockReflowState.h" 13 #include "JustificationUtils.h" 14 #include "gfxTextRun.h" 15 #include "gfxTypes.h" 16 #include "mozilla/ArenaAllocator.h" 17 #include "mozilla/WritingModes.h" 18 #include "nsLineBox.h" 19 20 class nsFloatManager; 21 struct nsStyleText; 22 23 class nsLineLayout { 24 using BlockReflowState = mozilla::BlockReflowState; 25 using ReflowInput = mozilla::ReflowInput; 26 using ReflowOutput = mozilla::ReflowOutput; 27 28 public: 29 /** 30 * @param aBaseLineLayout the nsLineLayout for ruby base, 31 * nullptr if no separate base nsLineLayout is needed. 32 */ 33 nsLineLayout(nsPresContext* aPresContext, nsFloatManager* aFloatManager, 34 const ReflowInput& aLineContainerRI, 35 const nsLineList::iterator* aLine, 36 nsLineLayout* aBaseLineLayout); 37 38 ~nsLineLayout() { 39 MOZ_COUNT_DTOR(nsLineLayout); 40 MOZ_ASSERT(!mRootSpan, "bad line-layout user"); 41 } 42 43 void Init(BlockReflowState* aState, nscoord aMinLineBSize, 44 int32_t aLineNumber) { 45 mBlockRS = aState; 46 mMinLineBSize = aMinLineBSize; 47 mLineNumber = aLineNumber; 48 } 49 50 int32_t GetLineNumber() const { return mLineNumber; } 51 52 void BeginLineReflow(nscoord aICoord, nscoord aBCoord, nscoord aISize, 53 nscoord aBSize, bool aImpactedByFloats, 54 bool aIsTopOfPage, mozilla::WritingMode aWritingMode, 55 const nsSize& aContainerSize, 56 // aInset is used during text-wrap:balance to reduce 57 // the effective available space on the line. 58 nscoord aInset = 0); 59 60 /** 61 * Returns true if the line had to use an overflow-wrap break position. 62 */ 63 bool EndLineReflow(); 64 65 /** 66 * Called when a float has been placed. This method updates the 67 * inline frame and span data to account for any change in positions 68 * due to available space for the line boxes changing. 69 * @param aX/aY/aWidth/aHeight are the new available 70 * space rectangle, relative to the containing block. 71 * @param aFloatFrame the float frame that was placed. 72 */ 73 void UpdateBand(mozilla::WritingMode aWM, 74 const mozilla::LogicalRect& aNewAvailableSpace, 75 nsIFrame* aFloatFrame); 76 77 void BeginSpan(nsIFrame* aFrame, const ReflowInput* aSpanReflowInput, 78 nscoord aLeftEdge, nscoord aRightEdge, nscoord* aBaseline); 79 80 // Returns the width of the span 81 nscoord EndSpan(nsIFrame* aFrame); 82 83 // This method attaches the last frame reflowed in this line layout 84 // to that in the base line layout. 85 void AttachLastFrameToBaseLineLayout() { 86 AttachFrameToBaseLineLayout(LastFrame()); 87 } 88 89 // This method attaches the root frame of this line layout to the 90 // last reflowed frame in the base line layout. 91 void AttachRootFrameToBaseLineLayout() { 92 AttachFrameToBaseLineLayout(mRootSpan->mFrame); 93 } 94 95 int32_t GetCurrentSpanCount() const; 96 97 void SplitLineTo(int32_t aNewCount); 98 99 bool IsZeroBSize() const; 100 101 // Reflows the frame and returns the reflow status. aPushedFrame is true 102 // if the frame is pushed to the next line because it doesn't fit. 103 void ReflowFrame(nsIFrame* aFrame, nsReflowStatus& aReflowStatus, 104 ReflowOutput* aMetrics, bool& aPushedFrame); 105 106 void AddMarkerFrame(nsIFrame* aFrame, const ReflowOutput& aMetrics); 107 108 void RemoveMarkerFrame(nsIFrame* aFrame); 109 110 /** 111 * Place frames in the block direction (CSS property vertical-align) 112 */ 113 void VerticalAlignLine(); 114 115 bool TrimTrailingWhiteSpace(); 116 117 /** 118 * Place frames in the inline direction (CSS property text-align). 119 */ 120 void TextAlignLine(nsLineBox* aLine, bool aIsLastLine); 121 122 /** 123 * Handle all the relative positioning in the line, compute the 124 * combined area (== overflow area) for the line, and handle view 125 * sizing/positioning and the setting of the overflow rect. 126 */ 127 void RelativePositionFrames(mozilla::OverflowAreas& aOverflowAreas) { 128 RelativePositionFrames(mRootSpan, aOverflowAreas); 129 } 130 131 // Support methods for word-wrapping during line reflow 132 133 void SetJustificationInfo(const mozilla::JustificationInfo& aInfo) { 134 mJustificationInfo = aInfo; 135 } 136 137 /** 138 * @return true if so far during reflow no non-empty content has been 139 * placed in the line (according to nsIFrame::IsEmpty()) 140 */ 141 bool LineIsEmpty() const { return mLineIsEmpty; } 142 143 /** 144 * @return true if so far during reflow no non-empty leaf content 145 * (non-collapsed whitespace, replaced element, inline-block, etc) has been 146 * placed in the line 147 */ 148 bool LineAtStart() const { return mLineAtStart; } 149 150 bool LineIsBreakable() const { 151 // XXX mTotalPlacedFrames should go away and we should just use 152 // mLineIsEmpty here instead 153 return mTotalPlacedFrames || mImpactedByFloats; 154 } 155 156 bool GetLineEndsInBR() const { return mLineEndsInBR; } 157 void SetLineEndsInBR(bool aOn) { mLineEndsInBR = aOn; } 158 159 //---------------------------------------- 160 // Inform the line-layout about the presence of a floating frame 161 // XXX get rid of this: use get-frame-type? 162 bool AddFloat(nsIFrame* aFloat, nscoord aAvailableISize) { 163 // When reflowing ruby text frames, no block reflow state is 164 // provided to the line layout. However, floats should never be 165 // associated with ruby text containers, hence this method should 166 // not be called in that case. 167 MOZ_ASSERT(mBlockRS, 168 "Should not call this method if there is no block reflow state " 169 "available"); 170 return mBlockRS->AddFloat(this, aFloat, aAvailableISize); 171 } 172 173 void SetTrimmableISize(nscoord aTrimmableISize) { 174 mTrimmableISize = aTrimmableISize; 175 } 176 177 //---------------------------------------- 178 179 bool GetFirstLetterStyleOK() const { return mFirstLetterStyleOK; } 180 void SetFirstLetterStyleOK(bool aSetting) { mFirstLetterStyleOK = aSetting; } 181 182 bool GetInFirstLetter() const { return mInFirstLetter; } 183 void SetInFirstLetter(bool aSetting) { mInFirstLetter = aSetting; } 184 185 bool GetInFirstLine() const { return mInFirstLine; } 186 void SetInFirstLine(bool aSetting) { mInFirstLine = aSetting; } 187 188 // Calling this during block reflow ensures that the next line of inlines 189 // will be marked dirty, if there is one. 190 void SetDirtyNextLine() { mDirtyNextLine = true; } 191 bool GetDirtyNextLine() const { return mDirtyNextLine; } 192 193 //---------------------------------------- 194 195 /** 196 * Record where an optional break could have been placed. During line reflow, 197 * frames containing optional break points (e.g., whitespace in text frames) 198 * can call SetLastOptionalBreakPosition to record where a break could 199 * have been made, but wasn't because we decided to place more content on 200 * the line. For non-text frames, offset 0 means before the frame, offset 201 * INT32_MAX means after the frame. 202 * 203 * Currently this is used to handle cases where a single word comprises 204 * multiple frames, and the first frame fits on the line but the whole word 205 * doesn't. We look back to the last optional break position and 206 * reflow the whole line again, forcing a break at that position. The last 207 * optional break position could be in a text frame or else after a frame 208 * that cannot be part of a text run, so those are the positions we record. 209 * 210 * @param aFrame the frame which contains the optional break position. 211 * 212 * @param aFits set to true if the break position is within the available 213 * width. 214 * 215 * @param aPriority the priority of the break opportunity. If we are 216 * prioritizing break opportunities, we will not set a break if we have 217 * already set a break with a higher priority. @see gfxBreakPriority. 218 * 219 * @return true if we are actually reflowing with forced break position and we 220 * should break here 221 */ 222 bool NotifyOptionalBreakPosition(nsIFrame* aFrame, int32_t aOffset, 223 bool aFits, gfxBreakPriority aPriority); 224 225 // Tries to place a float, and records whether the float actually was placed. 226 bool TryToPlaceFloat(nsIFrame* aFloat); 227 228 // Records a floating frame in a nowrap context for it to be placed on the 229 // next break opportunity. 230 void RecordNoWrapFloat(nsIFrame* aFloat); 231 232 // Tries to place the floats from the nowrap context. 233 void FlushNoWrapFloats(); 234 235 /** 236 * Like NotifyOptionalBreakPosition, but here it's OK for mNeedBackup 237 * to be set, because the caller is merely pruning some saved break 238 * position(s) that are actually not feasible. 239 */ 240 void RestoreSavedBreakPosition(nsIFrame* aFrame, int32_t aOffset, 241 gfxBreakPriority aPriority) { 242 mLastOptionalBreakFrame = aFrame; 243 mLastOptionalBreakFrameOffset = aOffset; 244 mLastOptionalBreakPriority = aPriority; 245 } 246 /** 247 * Signal that no backing up will be required after all. 248 */ 249 void ClearOptionalBreakPosition() { 250 mNeedBackup = false; 251 mLastOptionalBreakFrame = nullptr; 252 mLastOptionalBreakFrameOffset = -1; 253 mLastOptionalBreakPriority = gfxBreakPriority::eNoBreak; 254 } 255 // Retrieve last set optional break position. When this returns null, no 256 // optional break has been recorded (which means that the line can't break 257 // yet). 258 nsIFrame* GetLastOptionalBreakPosition(int32_t* aOffset, 259 gfxBreakPriority* aPriority) { 260 *aOffset = mLastOptionalBreakFrameOffset; 261 *aPriority = mLastOptionalBreakPriority; 262 return mLastOptionalBreakFrame; 263 } 264 // Whether any optional break position has been recorded. 265 bool HasOptionalBreakPosition() const { 266 return mLastOptionalBreakFrame != nullptr; 267 } 268 // Get the priority of the last optional break position recorded. 269 gfxBreakPriority LastOptionalBreakPriority() const { 270 return mLastOptionalBreakPriority; 271 } 272 273 /** 274 * Check whether frames overflowed the available width and CanPlaceFrame 275 * requested backing up to a saved break position. 276 */ 277 bool NeedsBackup() { return mNeedBackup; } 278 279 // Line layout may place too much content on a line, overflowing its available 280 // width. When that happens, if SetLastOptionalBreakPosition has been 281 // used to record an optional break that wasn't taken, we can reflow the line 282 // again and force the break to happen at that point (i.e., backtracking 283 // to the last choice point). 284 285 // Record that we want to break at the given content+offset (which 286 // should have been previously returned by GetLastOptionalBreakPosition 287 // from another nsLineLayout). 288 void ForceBreakAtPosition(nsIFrame* aFrame, int32_t aOffset) { 289 mForceBreakFrame = aFrame; 290 mForceBreakFrameOffset = aOffset; 291 } 292 bool HaveForcedBreakPosition() { return mForceBreakFrame != nullptr; } 293 int32_t GetForcedBreakPosition(nsIFrame* aFrame) { 294 return mForceBreakFrame == aFrame ? mForceBreakFrameOffset : -1; 295 } 296 297 /** 298 * This can't be null. It usually returns a block frame but may return 299 * some other kind of frame when inline frames are reflowed in a non-block 300 * context (e.g. MathML or floating first-letter). 301 */ 302 nsIFrame* LineContainerFrame() const { return mLineContainerRI.mFrame; } 303 const ReflowInput& LineContainerRI() const { return mLineContainerRI; } 304 const nsLineList::iterator* GetLine() const { 305 return mGotLineBox ? &mLineBox : nullptr; 306 } 307 nsLineList::iterator* GetLine() { return mGotLineBox ? &mLineBox : nullptr; } 308 309 /** 310 * Returns the accumulated advance width of frames before the current frame 311 * on the line, plus the line container's left border+padding. 312 * This is always positive, the advance width is measured from 313 * the right edge for RTL blocks and from the left edge for LTR blocks. 314 * In other words, the current frame's distance from the line container's 315 * start content edge is: 316 * <code>GetCurrentFrameInlineDistanceFromBlock() - 317 * lineContainer->GetUsedBorderAndPadding().left</code> Note the use of 318 * <code>.left</code> for both LTR and RTL line containers. 319 */ 320 nscoord GetCurrentFrameInlineDistanceFromBlock(); 321 322 /** 323 * Move the inline position where the next frame will be reflowed forward by 324 * aAmount. 325 */ 326 void AdvanceICoord(nscoord aAmount) { mCurrentSpan->mICoord += aAmount; } 327 /** 328 * Returns the writing mode for the root span. 329 */ 330 mozilla::WritingMode GetWritingMode() { return mRootSpan->mWritingMode; } 331 /** 332 * Returns the inline position where the next frame will be reflowed. 333 */ 334 nscoord GetCurrentICoord() { return mCurrentSpan->mICoord; } 335 336 void SetSuppressLineWrap(bool aEnabled) { mSuppressLineWrap = aEnabled; } 337 338 /** 339 * Record that the line had to resort to an overflow-wrap break. 340 */ 341 void SetUsedOverflowWrap() { mUsedOverflowWrap = true; } 342 343 protected: 344 // This state is constant for a given block frame doing line layout 345 346 nsPresContext* const mPresContext; 347 348 // A non-owning pointer, which points to the object owned by 349 // nsAutoFloatManager::mNew. 350 nsFloatManager* const mFloatManager; 351 352 const nsStyleText* mStyleText; // for the block 353 const ReflowInput& mLineContainerRI; 354 355 // The line layout for the base text. It is usually nullptr. 356 // It becomes not null when the current line layout is for ruby 357 // annotations. When there is nested ruby inside annotation, it 358 // forms a linked list from the inner annotation to the outermost 359 // line layout. The outermost line layout, which has this member 360 // being nullptr, is responsible for managing the life cycle of 361 // per-frame data and per-span data, and handling floats. 362 nsLineLayout* const mBaseLineLayout; 363 364 nsLineLayout* GetOutermostLineLayout() { 365 nsLineLayout* lineLayout = this; 366 while (lineLayout->mBaseLineLayout) { 367 lineLayout = lineLayout->mBaseLineLayout; 368 } 369 return lineLayout; 370 } 371 372 nsIFrame* mLastOptionalBreakFrame = nullptr; 373 nsIFrame* mForceBreakFrame = nullptr; 374 375 // XXX Take care that nsRubyBaseContainer would give nullptr to this 376 // member. It should not be a problem currently, since the only 377 // code use it is handling float, which does not affect ruby. 378 // See comment in nsLineLayout::AddFloat 379 BlockReflowState* mBlockRS = nullptr; /* XXX hack! */ 380 381 nsLineList::iterator mLineBox; 382 383 // Per-frame data recorded by the line-layout reflow logic. This 384 // state is the state needed to post-process the line after reflow 385 // has completed (block-direction alignment, inline-direction alignment, 386 // justification and relative positioning). 387 struct PerSpanData; 388 struct PerFrameData { 389 // link to next/prev frame in same span 390 PerFrameData* mNext; 391 PerFrameData* mPrev; 392 393 // Link to the frame of next ruby annotation. It is a linked list 394 // through this pointer from ruby base to all its annotations. It 395 // could be nullptr if there is no more annotation. 396 // If PFD_ISLINKEDTOBASE is set, the current PFD is one of the ruby 397 // annotations in the base's list, otherwise it is the ruby base, 398 // and its mNextAnnotation is the start of the linked list. 399 PerFrameData* mNextAnnotation; 400 401 // pointer to child span data if this is an inline container frame 402 PerSpanData* mSpan; 403 404 // The frame 405 nsIFrame* mFrame; 406 407 // From metrics 408 nscoord mAscent; 409 // note that mBounds is a logical rect in the *line*'s writing mode. 410 // When setting frame coordinates, we have to convert to the frame's 411 // writing mode 412 mozilla::LogicalRect mBounds; 413 mozilla::OverflowAreas mOverflowAreas; 414 415 // From reflow-state 416 mozilla::LogicalMargin mMargin; // in *line* writing mode 417 mozilla::LogicalMargin mBorderPadding; // in *line* writing mode 418 mozilla::LogicalMargin mOffsets; // in *frame* writing mode 419 420 // state for text justification 421 // Note that, although all frames would have correct inner 422 // opportunities computed after ComputeFrameJustification, start 423 // and end justifiable info are not reliable for non-text frames. 424 mozilla::JustificationInfo mJustificationInfo; 425 mozilla::JustificationAssignment mJustificationAssignment; 426 427 // PerFrameData flags 428 bool mIsRelativelyOrStickyPos : 1; 429 bool mIsTextFrame : 1; 430 bool mIsNonEmptyTextFrame : 1; 431 bool mIsNonWhitespaceTextFrame : 1; 432 bool mIsLetterFrame : 1; 433 bool mRecomputeOverflow : 1; 434 bool mIsMarker : 1; 435 bool mSkipWhenTrimmingWhitespace : 1; 436 bool mIsEmpty : 1; 437 bool mIsPlaceholder : 1; 438 bool mIsLinkedToBase : 1; 439 440 // Other state we use 441 uint8_t mBlockDirAlign; 442 mozilla::WritingMode mWritingMode; 443 444 PerFrameData* Last() { 445 PerFrameData* pfd = this; 446 while (pfd->mNext) { 447 pfd = pfd->mNext; 448 } 449 return pfd; 450 } 451 452 bool IsStartJustifiable() const { 453 return mJustificationInfo.mIsStartJustifiable; 454 } 455 456 bool IsEndJustifiable() const { 457 return mJustificationInfo.mIsEndJustifiable; 458 } 459 460 bool ParticipatesInJustification() const; 461 }; 462 PerFrameData* mFrameFreeList = nullptr; 463 464 // In nsLineLayout, a "span" is a container inline frame, and a "frame" is one 465 // of its children. 466 // 467 // nsLineLayout::BeginLineReflow() creates the initial PerSpanData which is 468 // called the "root span". nsInlineFrame::ReflowFrames() creates a new 469 // PerSpanData when it calls nsLineLayout::BeginSpan(); at this time, the 470 // nsLineLayout object's mCurrentSpan is switched to the new span. The new 471 // span records the old mCurrentSpan as its parent. After reflowing the child 472 // inline frames, nsInlineFrame::ReflowFrames() calls nsLineLayout::EndSpan(), 473 // which pops the PerSpanData and re-sets mCurrentSpan. 474 struct PerSpanData { 475 union { 476 PerSpanData* mParent; 477 PerSpanData* mNextFreeSpan; 478 }; 479 480 // The PerFrameData of the inline frame that "owns" the span, or null if 481 // this is the root span. mFrame is initialized to the containing inline 482 // frame's PerFrameData when a new PerSpanData is pushed in 483 // nsLineLayout::BeginSpan(). 484 PerFrameData* mFrame; 485 486 // The first PerFrameData structure in the span. 487 PerFrameData* mFirstFrame; 488 489 // The last PerFrameData structure in the span. PerFrameData structures are 490 // added to the span as they are reflowed. mLastFrame may also be directly 491 // manipulated if a line is split, or if frames are pushed from one line to 492 // the next. 493 PerFrameData* mLastFrame; 494 495 const ReflowInput* mReflowInput; 496 bool mNoWrap; 497 mozilla::WritingMode mWritingMode; 498 bool mContainsFloat; 499 bool mHasNonemptyContent; 500 501 nscoord mIStart; 502 nscoord mICoord; 503 nscoord mIEnd; 504 nscoord mInset; 505 506 nscoord mBStartLeading, mBEndLeading; 507 nscoord mLogicalBSize; 508 nscoord mMinBCoord, mMaxBCoord; 509 nscoord* mBaseline; 510 511 void AppendFrame(PerFrameData* pfd) { 512 if (!mLastFrame) { 513 mFirstFrame = pfd; 514 } else { 515 mLastFrame->mNext = pfd; 516 pfd->mPrev = mLastFrame; 517 } 518 mLastFrame = pfd; 519 } 520 }; 521 PerSpanData* mSpanFreeList = nullptr; 522 PerSpanData* mRootSpan = nullptr; 523 PerSpanData* mCurrentSpan = nullptr; 524 525 // The container size to use when converting between logical and 526 // physical coordinates for frames in this span. For the root span 527 // this is the size of the block cached in mContainerSize; for 528 // child spans it's the size of the root span. 529 nsSize ContainerSizeForSpan(PerSpanData* aPSD) { 530 return (aPSD == mRootSpan) 531 ? mContainerSize 532 : aPSD->mFrame->mBounds.Size(mRootSpan->mWritingMode) 533 .GetPhysicalSize(mRootSpan->mWritingMode); 534 } 535 536 // Get the advance of any trailing hangable whitespace. If the whitespace 537 // has directionality opposite to the line, the result is negated. 538 nscoord GetHangFrom(const PerSpanData* aSpan, bool aLineIsRTL) const; 539 gfxTextRun::TrimmableWS GetTrimFrom(const PerSpanData* aSpan, 540 bool aLineIsRTL) const; 541 542 gfxBreakPriority mLastOptionalBreakPriority = gfxBreakPriority::eNoBreak; 543 int32_t mLastOptionalBreakFrameOffset = -1; 544 int32_t mForceBreakFrameOffset = -1; 545 546 nscoord mMinLineBSize = 0; 547 548 // The amount of text indent that we applied to this line, needed for 549 // max-element-size calculation. 550 nscoord mTextIndent = 0; 551 552 // This state varies during the reflow of a line but is line 553 // "global" state not span "local" state. 554 int32_t mLineNumber = 0; 555 mozilla::JustificationInfo mJustificationInfo; 556 557 int32_t mTotalPlacedFrames = 0; 558 559 nscoord mBStartEdge = 0; 560 nscoord mMaxStartBoxBSize = 0; 561 nscoord mMaxEndBoxBSize = 0; 562 563 nscoord mInflationMinFontSize; 564 565 // Final computed line-bSize value after VerticalAlignFrames for 566 // the block has been called. 567 nscoord mFinalLineBSize = 0; 568 569 // Amount of trimmable whitespace inline size for the trailing text 570 // frame, if any 571 nscoord mTrimmableISize = 0; 572 573 // Physical size. Use only for physical <-> logical coordinate conversion. 574 nsSize mContainerSize; 575 const nsSize& ContainerSize() const { return mContainerSize; } 576 577 bool mFirstLetterStyleOK : 1; 578 bool mIsTopOfPage : 1; 579 bool mImpactedByFloats : 1; 580 bool mLastFloatWasLetterFrame : 1; 581 bool mLineIsEmpty : 1; 582 bool mLineEndsInBR : 1; 583 bool mNeedBackup : 1; 584 bool mInFirstLine : 1; 585 bool mGotLineBox : 1; 586 bool mInFirstLetter : 1; 587 bool mHasMarker : 1; 588 bool mDirtyNextLine : 1; 589 bool mLineAtStart : 1; 590 bool mHasRuby : 1; 591 bool mSuppressLineWrap : 1; 592 bool mUsedOverflowWrap : 1; 593 594 int32_t mSpanDepth = 0; 595 #ifdef DEBUG 596 int32_t mSpansAllocated = 0, mSpansFreed = 0; 597 int32_t mFramesAllocated = 0, mFramesFreed = 0; 598 #endif 599 600 /** 601 * Per span and per frame data. 602 */ 603 mozilla::ArenaAllocator<1024, sizeof(void*)> mArena; 604 605 /** 606 * Allocate a PerFrameData from the mArena pool. The allocation is infallible. 607 */ 608 PerFrameData* NewPerFrameData(nsIFrame* aFrame); 609 610 /** 611 * Allocate a PerSpanData from the mArena pool. The allocation is infallible. 612 */ 613 PerSpanData* NewPerSpanData(); 614 615 PerFrameData* LastFrame() const { return mCurrentSpan->mLastFrame; } 616 617 /** 618 * Unlink the given PerFrameData and all the siblings after it from 619 * the span. The unlinked PFDs are usually freed immediately. 620 * However, if PFD_ISLINKEDTOBASE is set, it won't be freed until 621 * the frame of its base is unlinked. 622 */ 623 void UnlinkFrame(PerFrameData* pfd); 624 625 /** 626 * Free the given PerFrameData. 627 */ 628 void FreeFrame(PerFrameData* pfd); 629 630 void FreeSpan(PerSpanData* psd); 631 632 bool InBlockContext() const { return mSpanDepth == 0; } 633 634 void PushFrame(nsIFrame* aFrame); 635 636 void AllowForStartMargin(PerFrameData* pfd, ReflowInput& aReflowInput); 637 638 void SyncAnnotationBounds(PerFrameData* aRubyFrame); 639 640 bool CanPlaceFrame(PerFrameData* pfd, bool aNotSafeToBreak, 641 bool aFrameCanContinueTextRun, 642 bool aCanRollBackBeforeFrame, ReflowOutput& aMetrics, 643 nsReflowStatus& aStatus, bool* aOptionalBreakAfterFits); 644 645 void PlaceFrame(PerFrameData* pfd, ReflowOutput& aMetrics); 646 647 void AdjustLeadings(nsIFrame* spanFrame, PerSpanData* psd, 648 const nsStyleText* aStyleText, float aInflation, 649 bool* aZeroEffectiveSpanBox); 650 651 static void SetSpanForEmptyLine(PerSpanData* aPerSpanData, 652 mozilla::WritingMode aWM, 653 const nsSize& aContainerSize, 654 nscoord aBStartEdge); 655 void VerticalAlignFrames(PerSpanData* psd); 656 657 void PlaceTopBottomFrames(PerSpanData* psd, nscoord aDistanceFromStart, 658 nscoord aLineBSize); 659 660 void ApplyRelativePositioning(PerFrameData* aPFD); 661 662 void RelativePositionAnnotations(PerSpanData* aRubyPSD, 663 mozilla::OverflowAreas& aOverflowAreas); 664 665 void RelativePositionFrames(PerSpanData* psd, 666 mozilla::OverflowAreas& aOverflowAreas); 667 668 bool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaISize); 669 670 struct JustificationComputationState; 671 672 static int AssignInterframeJustificationGaps( 673 PerFrameData* aFrame, JustificationComputationState& aState); 674 675 int32_t ComputeFrameJustification(PerSpanData* psd, 676 JustificationComputationState& aState); 677 678 void AdvanceAnnotationInlineBounds(PerFrameData* aPFD, 679 const nsSize& aContainerSize, 680 nscoord aDeltaICoord, nscoord aDeltaISize); 681 682 void ApplyLineJustificationToAnnotations(PerFrameData* aPFD, 683 nscoord aDeltaICoord, 684 nscoord aDeltaISize); 685 686 // Apply justification. The return value is the amount by which the width of 687 // the span corresponding to aPSD got increased due to justification. 688 nscoord ApplyFrameJustification( 689 PerSpanData* aPSD, mozilla::JustificationApplicationState& aState); 690 691 void ExpandRubyBox(PerFrameData* aFrame, nscoord aReservedISize, 692 const nsSize& aContainerSize); 693 694 void ExpandRubyBoxWithAnnotations(PerFrameData* aFrame, 695 const nsSize& aContainerSize); 696 697 void ExpandInlineRubyBoxes(PerSpanData* aSpan); 698 699 void AttachFrameToBaseLineLayout(PerFrameData* aFrame); 700 701 #ifdef DEBUG 702 void DumpPerSpanData(PerSpanData* psd, int32_t aIndent); 703 #endif 704 705 private: 706 static bool ShouldApplyLineHeightInPreserveWhiteSpace(const PerSpanData* psd); 707 }; 708 709 #endif /* nsLineLayout_h___ */