Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/nsFrame.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
/* base class of all rendering objects */
8
9
#ifndef nsFrame_h___
10
#define nsFrame_h___
11
12
#include "mozilla/Attributes.h"
13
#include "mozilla/EventForwards.h"
14
#include "mozilla/Likely.h"
15
#include "nsBox.h"
16
#include "mozilla/Logging.h"
17
18
#include "nsIPresShell.h"
19
#include "mozilla/ReflowInput.h"
20
#include "nsHTMLParts.h"
21
#include "nsISelectionDisplay.h"
22
23
namespace mozilla {
24
enum class TableSelection : uint32_t;
25
} // namespace mozilla
26
27
/**
28
 * nsFrame logging constants. We redefine the nspr
29
 * PRLogModuleInfo.level field to be a bitfield.  Each bit controls a
30
 * specific type of logging. Each logging operation has associated
31
 * inline methods defined below.
32
 *
33
 * Due to the redefinition of the level field we cannot use MOZ_LOG directly
34
 * as that will cause assertions due to invalid log levels.
35
 */
36
#define NS_FRAME_TRACE_CALLS        0x1
37
#define NS_FRAME_TRACE_PUSH_PULL    0x2
38
#define NS_FRAME_TRACE_CHILD_REFLOW 0x4
39
#define NS_FRAME_TRACE_NEW_FRAMES   0x8
40
41
#define NS_FRAME_LOG_TEST(_lm,_bit) (int(((mozilla::LogModule*)_lm)->Level()) & (_bit))
42
43
#ifdef DEBUG
44
#define NS_FRAME_LOG(_bit,_args)                                \
45
  PR_BEGIN_MACRO                                                \
46
    if (NS_FRAME_LOG_TEST(nsFrame::sFrameLogModule,_bit)) {  \
47
      printf_stderr _args; \
48
    }                                                           \
49
  PR_END_MACRO
50
#else
51
#define NS_FRAME_LOG(_bit,_args)
52
#endif
53
54
// XXX Need to rework this so that logging is free when it's off
55
#ifdef DEBUG
56
#define NS_FRAME_TRACE_IN(_method) Trace(_method, true)
57
58
#define NS_FRAME_TRACE_OUT(_method) Trace(_method, false)
59
60
// XXX remove me
61
#define NS_FRAME_TRACE_MSG(_bit,_args)                          \
62
  PR_BEGIN_MACRO                                                \
63
    if (NS_FRAME_LOG_TEST(nsFrame::sFrameLogModule,_bit)) {  \
64
      TraceMsg _args;                                           \
65
    }                                                           \
66
  PR_END_MACRO
67
68
#define NS_FRAME_TRACE(_bit,_args)                              \
69
  PR_BEGIN_MACRO                                                \
70
    if (NS_FRAME_LOG_TEST(nsFrame::sFrameLogModule,_bit)) {  \
71
      TraceMsg _args;                                           \
72
    }                                                           \
73
  PR_END_MACRO
74
75
#define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, true)
76
77
#define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
78
  Trace(_method, false, _status)
79
80
#else
81
#define NS_FRAME_TRACE(_bits,_args)
82
#define NS_FRAME_TRACE_IN(_method)
83
#define NS_FRAME_TRACE_OUT(_method)
84
#define NS_FRAME_TRACE_MSG(_bits,_args)
85
#define NS_FRAME_TRACE_REFLOW_IN(_method)
86
#define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
87
#endif
88
89
// Frame allocation boilerplate macros. Every subclass of nsFrame must
90
// either use NS_{DECL,IMPL}_FRAMEARENA_HELPERS pair for allocating
91
// memory correctly, or use NS_DECL_ABSTRACT_FRAME to declare a frame
92
// class abstract and stop it from being instantiated. If a frame class
93
// without its own operator new and GetFrameId gets instantiated, the
94
// per-frame recycler lists in nsPresArena will not work correctly,
95
// with potentially catastrophic consequences (not enough memory is
96
// allocated for a frame object).
97
98
#define NS_DECL_FRAMEARENA_HELPERS(class)                           \
99
  NS_DECL_QUERYFRAME_TARGET(class)                                  \
100
  static constexpr nsIFrame::ClassID kClassID = nsIFrame::ClassID::class##_id;  \
101
  void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE;      \
102
  nsQueryFrame::FrameIID GetFrameId() override MOZ_MUST_OVERRIDE {  \
103
    return nsQueryFrame::class##_id;                                \
104
  }
105
106
#define NS_IMPL_FRAMEARENA_HELPERS(class)                         \
107
  void* class::operator new(size_t sz, nsIPresShell* aShell)      \
108
  { return aShell->AllocateFrame(nsQueryFrame::class##_id, sz); } \
109
110
#define NS_DECL_ABSTRACT_FRAME(class)                                   \
111
  void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE = delete; \
112
  virtual nsQueryFrame::FrameIID GetFrameId() override MOZ_MUST_OVERRIDE = 0;
113
114
//----------------------------------------------------------------------
115
116
struct nsBoxLayoutMetrics;
117
struct nsRect;
118
119
/**
120
 * Implementation of a simple frame that's not splittable and has no
121
 * child frames.
122
 *
123
 * Sets the NS_FRAME_SYNCHRONIZE_FRAME_AND_VIEW bit, so the default
124
 * behavior is to keep the frame and view position and size in sync.
125
 */
126
class nsFrame : public nsBox
127
{
128
public:
129
  /**
130
   * Create a new "empty" frame that maps a given piece of content into a
131
   * 0,0 area.
132
   */
133
  friend nsIFrame* NS_NewEmptyFrame(nsIPresShell* aShell,
134
                                    ComputedStyle* aStyle);
135
136
private:
137
  // Left undefined; nsFrame objects are never allocated from the heap.
138
  void* operator new(size_t sz) CPP_THROW_NEW;
139
140
protected:
141
  // Overridden to prevent the global delete from being called, since
142
  // the memory came out of an arena instead of the heap.
143
  //
144
  // Ideally this would be private and undefined, like the normal
145
  // operator new.  Unfortunately, the C++ standard requires an
146
  // overridden operator delete to be accessible to any subclass that
147
  // defines a virtual destructor, so we can only make it protected;
148
  // worse, some C++ compilers will synthesize calls to this function
149
  // from the "deleting destructors" that they emit in case of
150
  // delete-expressions, so it can't even be undefined.
151
  void operator delete(void* aPtr, size_t sz);
152
153
public:
154
155
  // nsQueryFrame
156
  NS_DECL_QUERYFRAME
157
  NS_DECL_QUERYFRAME_TARGET(nsFrame)
158
  virtual nsQueryFrame::FrameIID GetFrameId() MOZ_MUST_OVERRIDE {
159
    return kFrameIID;
160
  }
161
  void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE;
162
163
  // nsIFrame
164
  void Init(nsIContent*       aContent,
165
            nsContainerFrame* aParent,
166
            nsIFrame*         aPrevInFlow) override;
167
  void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
168
  ComputedStyle* GetAdditionalComputedStyle(int32_t aIndex) const override;
169
  void SetAdditionalComputedStyle(int32_t aIndex,
170
                                  ComputedStyle* aComputedStyle) override;
171
  nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;
172
  const nsFrameList& GetChildList(ChildListID aListID) const override;
173
  void GetChildLists(nsTArray<ChildList>* aLists) const override;
174
175
  nsresult HandleEvent(nsPresContext* aPresContext,
176
                       mozilla::WidgetGUIEvent* aEvent,
177
                       nsEventStatus* aEventStatus) override;
178
  nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
179
                              nsIContent** aContent) override;
180
  nsresult GetCursor(const nsPoint&    aPoint,
181
                     nsIFrame::Cursor& aCursor) override;
182
183
  nsresult GetPointFromOffset(int32_t  inOffset,
184
                              nsPoint* outPoint) override;
185
  nsresult GetCharacterRectsInRange(int32_t aInOffset,
186
                                    int32_t aLength,
187
                                    nsTArray<nsRect>& aOutRect) override;
188
189
  nsresult GetChildFrameContainingOffset(int32_t    inContentOffset,
190
                                         bool       inHint,
191
                                         int32_t*   outFrameContentOffset,
192
                                         nsIFrame** outChildFrame) override;
193
194
  static nsresult GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
195
                                                 nsPeekOffsetStruct *aPos,
196
                                                 nsIFrame *aBlockFrame,
197
                                                 int32_t aLineStart,
198
                                                 int8_t aOutSideLimit);
199
200
  nsresult CharacterDataChanged(const CharacterDataChangeInfo& aInfo) override;
201
  nsresult AttributeChanged(int32_t  aNameSpaceID,
202
                            nsAtom* aAttribute,
203
                            int32_t aModType) override;
204
  nsSplittableType GetSplittableType() const override;
205
  nsIFrame* GetPrevContinuation() const override;
206
  void SetPrevContinuation(nsIFrame*) override;
207
  nsIFrame* GetNextContinuation() const override;
208
  void SetNextContinuation(nsIFrame*) override;
209
  nsIFrame* GetPrevInFlowVirtual() const override;
210
  void SetPrevInFlow(nsIFrame*) override;
211
  nsIFrame* GetNextInFlowVirtual() const override;
212
  void SetNextInFlow(nsIFrame*) override;
213
214
  nsresult GetSelectionController(nsPresContext *aPresContext,
215
                                  nsISelectionController **aSelCon) override;
216
217
  FrameSearchResult PeekOffsetNoAmount(bool aForward,
218
                                       int32_t* aOffset) override;
219
  FrameSearchResult
220
  PeekOffsetCharacter(bool aForward, int32_t* aOffset,
221
                      PeekOffsetCharacterOptions aOptions =
222
                                PeekOffsetCharacterOptions()) override;
223
  FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace,
224
                                   bool aIsKeyboardSelect,
225
                                   int32_t* aOffset,
226
                                   PeekWordState *aState) override;
227
  /**
228
   * Check whether we should break at a boundary between punctuation and
229
   * non-punctuation. Only call it at a punctuation boundary
230
   * (i.e. exactly one of the previous and next characters are punctuation).
231
   * @param aForward true if we're moving forward in content order
232
   * @param aPunctAfter true if the next character is punctuation
233
   * @param aWhitespaceAfter true if the next character is whitespace
234
   */
235
  bool BreakWordBetweenPunctuation(const PeekWordState* aState,
236
                                   bool aForward,
237
                                   bool aPunctAfter, bool aWhitespaceAfter,
238
                                   bool aIsKeyboardSelect);
239
240
  nsresult CheckVisibility(nsPresContext* aContext,
241
                           int32_t aStartIndex, int32_t aEndIndex,
242
                           bool aRecurse, bool *aFinished,
243
                           bool *_retval) override;
244
245
  nsresult GetOffsets(int32_t &aStart, int32_t &aEnd) const override;
246
  void ChildIsDirty(nsIFrame* aChild) override;
247
248
#ifdef ACCESSIBILITY
249
  mozilla::a11y::AccType AccessibleType() override;
250
#endif
251
252
  ComputedStyle* GetParentComputedStyle(nsIFrame** aProviderFrame) const override {
253
    return DoGetParentComputedStyle(aProviderFrame);
254
  }
255
256
  /**
257
   * Do the work for getting the parent ComputedStyle frame so that
258
   * other frame's |GetParentComputedStyle| methods can call this
259
   * method on *another* frame.  (This function handles out-of-flow
260
   * frames by using the frame manager's placeholder map and it also
261
   * handles block-within-inline and generated content wrappers.)
262
   *
263
   * @param aProviderFrame (out) the frame associated with the returned value
264
   *   or null if the ComputedStyle is for display:contents content.
265
   * @return The ComputedStyle that should be the parent of this frame's
266
   *   ComputedStyle.  Null is permitted, and means that this frame's
267
   *   ComputedStyle should be the root of the ComputedStyle tree.
268
   */
269
  ComputedStyle* DoGetParentComputedStyle(nsIFrame** aProviderFrame) const;
270
271
  bool IsEmpty() override;
272
  bool IsSelfEmpty() override;
273
274
  void MarkIntrinsicISizesDirty() override;
275
  nscoord GetMinISize(gfxContext *aRenderingContext) override;
276
  nscoord GetPrefISize(gfxContext *aRenderingContext) override;
277
  void AddInlineMinISize(gfxContext *aRenderingContext,
278
                         InlineMinISizeData *aData) override;
279
  void AddInlinePrefISize(gfxContext *aRenderingContext,
280
                          InlinePrefISizeData *aData) override;
281
  IntrinsicISizeOffsetData
282
  IntrinsicISizeOffsets(nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) override;
283
  mozilla::IntrinsicSize GetIntrinsicSize() override;
284
  nsSize GetIntrinsicRatio() override;
285
286
  mozilla::LogicalSize
287
  ComputeSize(gfxContext*                 aRenderingContext,
288
              mozilla::WritingMode        aWM,
289
              const mozilla::LogicalSize& aCBSize,
290
              nscoord                     aAvailableISize,
291
              const mozilla::LogicalSize& aMargin,
292
              const mozilla::LogicalSize& aBorder,
293
              const mozilla::LogicalSize& aPadding,
294
              ComputeSizeFlags            aFlags) override;
295
296
  /**
297
   * Calculate the used values for 'width' and 'height' for a replaced element.
298
   *   http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
299
   */
300
  mozilla::LogicalSize
301
  ComputeSizeWithIntrinsicDimensions(
302
              gfxContext*                   aRenderingContext,
303
              mozilla::WritingMode          aWM,
304
              const mozilla::IntrinsicSize& aIntrinsicSize,
305
              nsSize                        aIntrinsicRatio,
306
              const mozilla::LogicalSize&   aCBSize,
307
              const mozilla::LogicalSize&   aMargin,
308
              const mozilla::LogicalSize&   aBorder,
309
              const mozilla::LogicalSize&   aPadding,
310
              ComputeSizeFlags              aFlags);
311
312
  // Compute tight bounds assuming this frame honours its border, background
313
  // and outline, its children's tight bounds, and nothing else.
314
  nsRect ComputeSimpleTightBounds(mozilla::gfx::DrawTarget* aDrawTarget) const;
315
316
  /**
317
   * A helper, used by |nsFrame::ComputeSize| (for frames that need to
318
   * override only this part of ComputeSize), that computes the size
319
   * that should be returned when 'width', 'height', and
320
   * min/max-width/height are all 'auto' or equivalent.
321
   *
322
   * In general, frames that can accept any computed width/height should
323
   * override only ComputeAutoSize, and frames that cannot do so need to
324
   * override ComputeSize to enforce their width/height invariants.
325
   *
326
   * Implementations may optimize by returning a garbage width if
327
   * StylePosition()->mWidth.GetUnit() != eStyleUnit_Auto, and
328
   * likewise for height, since in such cases the result is guaranteed
329
   * to be unused.
330
   */
331
  virtual mozilla::LogicalSize
332
  ComputeAutoSize(gfxContext*                 aRenderingContext,
333
                  mozilla::WritingMode        aWM,
334
                  const mozilla::LogicalSize& aCBSize,
335
                  nscoord                     aAvailableISize,
336
                  const mozilla::LogicalSize& aMargin,
337
                  const mozilla::LogicalSize& aBorder,
338
                  const mozilla::LogicalSize& aPadding,
339
                  ComputeSizeFlags            aFlags);
340
341
  /**
342
   * Utility function for ComputeAutoSize implementations.  Return
343
   * max(GetMinISize(), min(aISizeInCB, GetPrefISize()))
344
   */
345
  nscoord ShrinkWidthToFit(gfxContext*         aRenderingContext,
346
                           nscoord             aISizeInCB,
347
                           ComputeSizeFlags    aFlags);
348
349
  /**
350
   * Calculates the size of this frame after reflowing (calling Reflow on, and
351
   * updating the size and position of) its children, as necessary.  The
352
   * calculated size is returned to the caller via the ReflowOutput
353
   * outparam.  (The caller is responsible for setting the actual size and
354
   * position of this frame.)
355
   *
356
   * A frame's children must _all_ be reflowed if the frame is dirty (the
357
   * NS_FRAME_IS_DIRTY bit is set on it).  Otherwise, individual children
358
   * must be reflowed if they are dirty or have the NS_FRAME_HAS_DIRTY_CHILDREN
359
   * bit set on them.  Otherwise, whether children need to be reflowed depends
360
   * on the frame's type (it's up to individual Reflow methods), and on what
361
   * has changed.  For example, a change in the width of the frame may require
362
   * all of its children to be reflowed (even those without dirty bits set on
363
   * them), whereas a change in its height might not.
364
   * (ReflowInput::ShouldReflowAllKids may be helpful in deciding whether
365
   * to reflow all the children, but for some frame types it might result in
366
   * over-reflow.)
367
   *
368
   * Note: if it's only the overflow rect(s) of a frame that need to be
369
   * updated, then UpdateOverflow should be called instead of Reflow.
370
   */
371
  void Reflow(nsPresContext*     aPresContext,
372
              ReflowOutput&      aDesiredSize,
373
              const ReflowInput& aReflowInput,
374
              nsReflowStatus&    aStatus) override;
375
  void DidReflow(nsPresContext*     aPresContext,
376
                 const ReflowInput* aReflowInput) override;
377
378
  /**
379
   * NOTE: aStatus is assumed to be already-initialized. The reflow statuses of
380
   * any reflowed absolute children will be merged into aStatus; aside from
381
   * that, this method won't modify aStatus.
382
   */
383
  void ReflowAbsoluteFrames(nsPresContext*     aPresContext,
384
                            ReflowOutput&      aDesiredSize,
385
                            const ReflowInput& aReflowInput,
386
                            nsReflowStatus&    aStatus,
387
                            bool               aConstrainBSize = true);
388
  void FinishReflowWithAbsoluteFrames(nsPresContext*     aPresContext,
389
                                      ReflowOutput&      aDesiredSize,
390
                                      const ReflowInput& aReflowInput,
391
                                      nsReflowStatus&    aStatus,
392
                                      bool aConstrainBSize = true);
393
394
  /*
395
   * If this frame is dirty, marks all absolutely-positioned children of this
396
   * frame dirty. If this frame isn't dirty, or if there are no
397
   * absolutely-positioned children, does nothing.
398
   *
399
   * It's necessary to use PushDirtyBitToAbsoluteFrames() when you plan to
400
   * reflow this frame's absolutely-positioned children after the dirty bit on
401
   * this frame has already been cleared, which prevents ReflowInput from
402
   * propagating the dirty bit normally. This situation generally only arises
403
   * when a multipass layout algorithm is used.
404
   */
405
  void PushDirtyBitToAbsoluteFrames();
406
407
  bool CanContinueTextRun() const override;
408
409
  bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override;
410
411
  void UnionChildOverflow(nsOverflowAreas& aOverflowAreas) override;
412
413
  // Selection Methods
414
415
  NS_IMETHOD HandlePress(nsPresContext* aPresContext,
416
                         mozilla::WidgetGUIEvent* aEvent,
417
                         nsEventStatus* aEventStatus);
418
419
  NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
420
                                 mozilla::WidgetGUIEvent* aEvent,
421
                                 nsEventStatus* aEventStatus,
422
                                 bool aControlHeld);
423
424
  NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
425
                        mozilla::WidgetGUIEvent* aEvent,
426
                        nsEventStatus* aEventStatus);
427
428
  NS_IMETHOD HandleRelease(nsPresContext* aPresContext,
429
                           mozilla::WidgetGUIEvent* aEvent,
430
                           nsEventStatus* aEventStatus);
431
432
  enum { SELECT_ACCUMULATE = 0x01 };
433
434
  nsresult PeekBackwardAndForward(nsSelectionAmount aAmountBack,
435
                                  nsSelectionAmount aAmountForward,
436
                                  int32_t aStartPos,
437
                                  bool aJumpLines,
438
                                  uint32_t aSelectFlags);
439
440
  nsresult SelectByTypeAtPoint(nsPresContext* aPresContext,
441
                               const nsPoint& aPoint,
442
                               nsSelectionAmount aBeginAmountType,
443
                               nsSelectionAmount aEndAmountType,
444
                               uint32_t aSelectFlags);
445
446
  // Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
447
  // in this function assumes there is no child frame that can be targeted.
448
  virtual ContentOffsets CalcContentOffsetsFromFramePoint(const nsPoint& aPoint);
449
450
  // Box layout methods
451
  nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
452
  nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
453
  nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
454
  nscoord GetXULFlex() override;
455
  nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
456
457
  // We compute and store the HTML content's overflow area. So don't
458
  // try to compute it in the box code.
459
  bool ComputesOwnOverflowArea() override { return true; }
460
461
  //--------------------------------------------------
462
  // Additional methods
463
464
  // Helper function that tests if the frame tree is too deep; if it is
465
  // it marks the frame as "unflowable", zeroes out the metrics, sets
466
  // the reflow status, and returns true. Otherwise, the frame is
467
  // unmarked "unflowable" and the metrics and reflow status are not
468
  // touched and false is returned.
469
  bool IsFrameTreeTooDeep(const ReflowInput& aReflowInput,
470
                            ReflowOutput& aMetrics,
471
                            nsReflowStatus& aStatus);
472
473
  // Incorporate the child overflow areas into aOverflowAreas.
474
  // If the child does not have a overflow, use the child area.
475
  void ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
476
                             nsIFrame* aChildFrame);
477
478
  /**
479
   * @return true if we should avoid a page/column break in this frame.
480
   */
481
  bool ShouldAvoidBreakInside(const ReflowInput& aReflowInput) const;
482
483
#ifdef DEBUG
484
  /**
485
   * Tracing method that writes a method enter/exit routine to the
486
   * nspr log using the nsIFrame log module. The tracing is only
487
   * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
488
   * level field.
489
   */
490
  void Trace(const char* aMethod, bool aEnter);
491
  void Trace(const char* aMethod, bool aEnter, const nsReflowStatus& aStatus);
492
  void TraceMsg(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
493
494
  // Helper function that verifies that each frame in the list has the
495
  // NS_FRAME_IS_DIRTY bit set
496
  static void VerifyDirtyBitSet(const nsFrameList& aFrameList);
497
498
  // Display Reflow Debugging
499
  static void* DisplayReflowEnter(nsPresContext*          aPresContext,
500
                                  nsIFrame*                aFrame,
501
                                  const ReflowInput& aReflowInput);
502
  static void* DisplayLayoutEnter(nsIFrame* aFrame);
503
  static void* DisplayIntrinsicISizeEnter(nsIFrame* aFrame,
504
                                          const char* aType);
505
  static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
506
                                         const char* aType);
507
  static void DisplayReflowExit(nsPresContext* aPresContext,
508
                                nsIFrame* aFrame,
509
                                ReflowOutput& aMetrics,
510
                                const nsReflowStatus& aStatus,
511
                                void* aFrameTreeNode);
512
  static void DisplayLayoutExit(nsIFrame* aFrame,
513
                                 void* aFrameTreeNode);
514
  static void DisplayIntrinsicISizeExit(nsIFrame* aFrame,
515
                                         const char* aType,
516
                                         nscoord aResult,
517
                                         void* aFrameTreeNode);
518
  static void DisplayIntrinsicSizeExit(nsIFrame* aFrame,
519
                                        const char* aType,
520
                                        nsSize aResult,
521
                                        void* aFrameTreeNode);
522
523
  static void DisplayReflowStartup();
524
  static void DisplayReflowShutdown();
525
#endif
526
527
  /**
528
   * Adds display items for standard CSS background if necessary.
529
   * Does not check IsVisibleForPainting.
530
   * @param aForceBackground draw the background even if the frame
531
   * background style appears to have no background --- this is useful
532
   * for frames that might receive a propagated background via
533
   * nsCSSRendering::FindBackground
534
   * @return whether a themed background item was created.
535
   */
536
  bool DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
537
                                      const nsDisplayListSet& aLists,
538
                                      bool aForceBackground);
539
  /**
540
   * Adds display items for standard CSS borders, background and outline for
541
   * for this frame, as necessary. Checks IsVisibleForPainting and won't
542
   * display anything if the frame is not visible.
543
   * @param aForceBackground draw the background even if the frame
544
   * background style appears to have no background --- this is useful
545
   * for frames that might receive a propagated background via
546
   * nsCSSRendering::FindBackground
547
   */
548
  void DisplayBorderBackgroundOutline(nsDisplayListBuilder*   aBuilder,
549
                                      const nsDisplayListSet& aLists,
550
                                      bool aForceBackground = false);
551
  /**
552
   * Add a display item for the CSS outline. Does not check visibility.
553
   */
554
  void DisplayOutlineUnconditional(nsDisplayListBuilder*   aBuilder,
555
                                   const nsDisplayListSet& aLists);
556
  /**
557
   * Add a display item for the CSS outline, after calling
558
   * IsVisibleForPainting to confirm we are visible.
559
   */
560
  void DisplayOutline(nsDisplayListBuilder*   aBuilder,
561
                      const nsDisplayListSet& aLists);
562
563
  /**
564
   * Adjust the given parent frame to the right ComputedStyle parent frame for
565
   * the child, given the pseudo-type of the prospective child.  This handles
566
   * things like walking out of table pseudos and so forth.
567
   *
568
   * @param aProspectiveParent what GetParent() on the child returns.
569
   *                           Must not be null.
570
   * @param aChildPseudo the child's pseudo type, if any.
571
   */
572
  static nsIFrame*
573
  CorrectStyleParentFrame(nsIFrame* aProspectiveParent, nsAtom* aChildPseudo);
574
575
protected:
576
  // Protected constructor and destructor
577
  nsFrame(ComputedStyle* aStyle, ClassID aID);
578
  explicit nsFrame(ComputedStyle* aStyle)
579
    : nsFrame(aStyle, ClassID::nsFrame_id) {}
580
  virtual ~nsFrame();
581
582
  /**
583
   * To be called by |BuildDisplayLists| of this class or derived classes to add
584
   * a translucent overlay if this frame's content is selected.
585
   * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
586
   * which kind of content this is for
587
   */
588
  void DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
589
      nsDisplayList* aList, uint16_t aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
590
591
  int16_t DisplaySelection(nsPresContext* aPresContext, bool isOkToTurnOn = false);
592
593
  // Style post processing hook
594
  void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
595
596
public:
597
  /**
598
   * Helper method to create a view for a frame.  Only used by a few sub-classes
599
   * that need a view.
600
   */
601
  void CreateView();
602
603
  //given a frame five me the first/last leaf available
604
  //XXX Robert O'Callahan wants to move these elsewhere
605
  static void GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
606
  static void GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
607
608
  // Return the line number of the aFrame, and (optionally) the containing block
609
  // frame.
610
  // If aScrollLock is true, don't break outside scrollframes when looking for a
611
  // containing block frame.
612
  static int32_t GetLineNumber(nsIFrame *aFrame,
613
                               bool aLockScroll,
614
                               nsIFrame** aContainingBlock = nullptr);
615
616
  /**
617
   * Returns true if aFrame should apply overflow clipping.
618
   */
619
  static bool ShouldApplyOverflowClipping(const nsIFrame* aFrame,
620
                                          const nsStyleDisplay* aDisp)
621
  {
622
    // clip overflow:-moz-hidden-unscrollable, except for nsListControlFrame,
623
    // which is an nsHTMLScrollFrame.
624
    if (MOZ_UNLIKELY(aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP &&
625
                     !aFrame->IsListControlFrame())) {
626
      return true;
627
    }
628
629
    // contain: paint, which we should interpret as -moz-hidden-unscrollable
630
    // by default.
631
    if (aDisp->IsContainPaint()) {
632
      return true;
633
    }
634
635
    // and overflow:hidden that we should interpret as -moz-hidden-unscrollable
636
    if (aDisp->mOverflowX == NS_STYLE_OVERFLOW_HIDDEN &&
637
        aDisp->mOverflowY == NS_STYLE_OVERFLOW_HIDDEN) {
638
      // REVIEW: these are the frame types that set up clipping.
639
      mozilla::LayoutFrameType type = aFrame->Type();
640
      if (type == mozilla::LayoutFrameType::Table ||
641
          type == mozilla::LayoutFrameType::TableCell ||
642
          type == mozilla::LayoutFrameType::BCTableCell ||
643
          type == mozilla::LayoutFrameType::SVGOuterSVG ||
644
          type == mozilla::LayoutFrameType::SVGInnerSVG ||
645
          type == mozilla::LayoutFrameType::SVGSymbol ||
646
          type == mozilla::LayoutFrameType::SVGForeignObject) {
647
        return true;
648
      }
649
      if (aFrame->IsFrameOfType(nsIFrame::eReplacedContainsBlock)) {
650
        if (type == mozilla::LayoutFrameType::TextInput) {
651
          // It always has an anonymous scroll frame that handles any overflow.
652
          return false;
653
        }
654
        return true;
655
      }
656
    }
657
658
    if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
659
      return false;
660
    }
661
662
    // If we're paginated and a block, and have NS_BLOCK_CLIP_PAGINATED_OVERFLOW
663
    // set, then we want to clip our overflow.
664
    return (aFrame->GetStateBits() & NS_BLOCK_CLIP_PAGINATED_OVERFLOW) != 0 &&
665
           aFrame->PresContext()->IsPaginated() && aFrame->IsBlockFrame();
666
  }
667
668
  nsILineIterator* GetLineIterator() override;
669
670
protected:
671
672
  // Test if we are selecting a table object:
673
  //  Most table/cell selection requires that Ctrl (Cmd on Mac) key is down
674
  //   during a mouse click or drag. Exception is using Shift+click when
675
  //   already in "table/cell selection mode" to extend a block selection
676
  //  Get the parent content node and offset of the frame
677
  //   of the enclosing cell or table (if not inside a cell)
678
  //  aTarget tells us what table element to select (currently only cell and table supported)
679
  //  (enums for this are defined in nsIFrame.h)
680
  nsresult GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
681
                                    nsIPresShell* aPresShell,
682
                                    mozilla::WidgetMouseEvent* aMouseEvent,
683
                                    nsIContent** aParentContent,
684
                                    int32_t* aContentOffset,
685
                                    mozilla::TableSelection* aTarget);
686
687
  // Fills aCursor with the appropriate information from ui
688
  static void FillCursorInformationFromStyle(const nsStyleUI* ui,
689
                                             nsIFrame::Cursor& aCursor);
690
  NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
691
692
  nsBoxLayoutMetrics* BoxMetrics() const;
693
694
  // Fire DOM event. If no aContent argument use frame's mContent.
695
  void FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent = nullptr);
696
697
private:
698
  void BoxReflow(nsBoxLayoutState& aState,
699
                 nsPresContext*    aPresContext,
700
                 ReflowOutput&     aDesiredSize,
701
                 gfxContext*       aRenderingContext,
702
                 nscoord aX,
703
                 nscoord aY,
704
                 nscoord aWidth,
705
                 nscoord aHeight,
706
                 bool aMoveFrame = true);
707
708
  NS_IMETHODIMP RefreshSizeCache(nsBoxLayoutState& aState);
709
710
  // Returns true if this frame has any kind of CSS animations.
711
  bool HasCSSAnimations();
712
713
  // Returns true if this frame has any kind of CSS transitions.
714
  bool HasCSSTransitions();
715
716
public:
717
718
#ifdef DEBUG_FRAME_DUMP
719
  /**
720
   * Get a printable from of the name of the frame type.
721
   * XXX This should be eliminated and we use GetType() instead...
722
   */
723
  nsresult GetFrameName(nsAString& aResult) const override;
724
  nsresult MakeFrameName(const nsAString& aKind, nsAString& aResult) const;
725
  // Helper function to return the index in parent of the frame's content
726
  // object. Returns -1 on error or if the frame doesn't have a content object
727
  static int32_t ContentIndexInContainer(const nsIFrame* aFrame);
728
#endif
729
730
#ifdef DEBUG
731
  static mozilla::LazyLogModule sFrameLogModule;
732
733
  // Show frame borders when rendering
734
  static void ShowFrameBorders(bool aEnable);
735
  static bool GetShowFrameBorders();
736
737
  // Show frame border of event target
738
  static void ShowEventTargetFrameBorder(bool aEnable);
739
  static bool GetShowEventTargetFrameBorder();
740
#endif
741
742
  static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
743
                               const nsDisplayList& aList,
744
                               bool aDumpHtml = false)
745
0
  {
746
0
    std::stringstream ss;
747
0
    PrintDisplayList(aBuilder, aList, ss, aDumpHtml);
748
0
    fprintf_stderr(stderr, "%s", ss.str().c_str());
749
0
  }
750
  static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
751
                               const nsDisplayList& aList,
752
                               std::stringstream& aStream,
753
                               bool aDumpHtml = false);
754
  static void PrintDisplayItem(nsDisplayListBuilder* aBuilder,
755
                               nsDisplayItem* aItem,
756
                               std::stringstream& aStream,
757
                               uint32_t aIndent = 0,
758
                               bool aDumpSublist = false,
759
                               bool aDumpHtml = false);
760
  static void PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
761
                                  const nsDisplayListSet& aList,
762
                                  std::stringstream& aStream,
763
                                  bool aDumpHtml = false);
764
765
};
766
767
// Start Display Reflow Debugging
768
#ifdef DEBUG
769
770
  struct DR_cookie {
771
    DR_cookie(nsPresContext*          aPresContext,
772
              nsIFrame*                aFrame,
773
              const mozilla::ReflowInput& aReflowInput,
774
              mozilla::ReflowOutput&     aMetrics,
775
              nsReflowStatus&          aStatus);
776
    ~DR_cookie();
777
    void Change() const;
778
779
    nsPresContext*          mPresContext;
780
    nsIFrame*                mFrame;
781
    const mozilla::ReflowInput& mReflowInput;
782
    mozilla::ReflowOutput&     mMetrics;
783
    nsReflowStatus&          mStatus;
784
    void*                    mValue;
785
  };
786
787
  struct DR_layout_cookie {
788
    explicit DR_layout_cookie(nsIFrame* aFrame);
789
    ~DR_layout_cookie();
790
791
    nsIFrame* mFrame;
792
    void* mValue;
793
  };
794
795
  struct DR_intrinsic_inline_size_cookie {
796
    DR_intrinsic_inline_size_cookie(nsIFrame* aFrame, const char* aType,
797
                              nscoord& aResult);
798
    ~DR_intrinsic_inline_size_cookie();
799
800
    nsIFrame* mFrame;
801
    const char* mType;
802
    nscoord& mResult;
803
    void* mValue;
804
  };
805
806
  struct DR_intrinsic_size_cookie {
807
    DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
808
                             nsSize& aResult);
809
    ~DR_intrinsic_size_cookie();
810
811
    nsIFrame* mFrame;
812
    const char* mType;
813
    nsSize& mResult;
814
    void* mValue;
815
  };
816
817
  struct DR_init_constraints_cookie {
818
    DR_init_constraints_cookie(nsIFrame* aFrame, mozilla::ReflowInput* aState,
819
                               nscoord aCBWidth, nscoord aCBHeight,
820
                               const nsMargin* aBorder,
821
                               const nsMargin* aPadding);
822
    ~DR_init_constraints_cookie();
823
824
    nsIFrame* mFrame;
825
    mozilla::ReflowInput* mState;
826
    void* mValue;
827
  };
828
829
  struct DR_init_offsets_cookie {
830
    DR_init_offsets_cookie(nsIFrame* aFrame, mozilla::SizeComputationInput* aState,
831
                           nscoord aPercentBasis,
832
                           mozilla::WritingMode aCBWritingMode,
833
                           const nsMargin* aBorder,
834
                           const nsMargin* aPadding);
835
    ~DR_init_offsets_cookie();
836
837
    nsIFrame* mFrame;
838
    mozilla::SizeComputationInput* mState;
839
    void* mValue;
840
  };
841
842
  struct DR_init_type_cookie {
843
    DR_init_type_cookie(nsIFrame* aFrame, mozilla::ReflowInput* aState);
844
    ~DR_init_type_cookie();
845
846
    nsIFrame* mFrame;
847
    mozilla::ReflowInput* mState;
848
    void* mValue;
849
  };
850
851
#define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status) \
852
  DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status);
853
#define DISPLAY_REFLOW_CHANGE() \
854
  dr_cookie.Change();
855
#define DISPLAY_LAYOUT(dr_frame) \
856
  DR_layout_cookie dr_cookie(dr_frame);
857
#define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
858
  DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Min", dr_result)
859
#define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
860
  DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
861
#define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
862
  DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
863
#define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
864
  DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
865
#define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
866
  DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
867
#define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh,       \
868
                                 dr_bdr, dr_pad)                           \
869
  DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh, \
870
                                       dr_bdr, dr_pad)
871
#define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr,      \
872
                             dr_pad)                                          \
873
  DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_cbwm,        \
874
                             dr_bdr, dr_pad)
875
#define DISPLAY_INIT_TYPE(dr_frame, dr_result) \
876
  DR_init_type_cookie dr_cookie(dr_frame, dr_result)
877
878
#else
879
880
#define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status)
881
#define DISPLAY_REFLOW_CHANGE()
882
#define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
883
#define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
884
#define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
885
#define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
886
#define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
887
#define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
888
#define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh,       \
889
                                 dr_bdr, dr_pad)                           \
890
  PR_BEGIN_MACRO PR_END_MACRO
891
#define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr,      \
892
                             dr_pad)                                          \
893
  PR_BEGIN_MACRO PR_END_MACRO
894
#define DISPLAY_INIT_TYPE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
895
896
#endif
897
// End Display Reflow Debugging
898
899
#endif /* nsFrame_h___ */