tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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___ */