Coverage Report

Created: 2018-09-25 14:53

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