Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/nsPlaceholderFrame.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
/*
8
 * rendering object for the point that anchors out-of-flow rendering
9
 * objects such as floats and absolutely positioned elements
10
 */
11
12
/*
13
 * Destruction of a placeholder and its out-of-flow must observe the
14
 * following constraints:
15
 *
16
 * - The mapping from the out-of-flow to the placeholder must be
17
 *   removed from the frame manager before the placeholder is destroyed.
18
 * - The mapping from the out-of-flow to the placeholder must be
19
 *   removed from the frame manager before the out-of-flow is destroyed.
20
 * - The placeholder must be removed from the frame tree, or have the
21
 *   mapping from it to its out-of-flow cleared, before the out-of-flow
22
 *   is destroyed (so that the placeholder will not point to a destroyed
23
 *   frame while it's in the frame tree).
24
 *
25
 * Furthermore, some code assumes that placeholders point to something
26
 * useful, so placeholders without an associated out-of-flow should not
27
 * remain in the tree.
28
 *
29
 * The placeholder's Destroy() implementation handles the destruction of
30
 * the placeholder and its out-of-flow. To avoid crashes, frame removal
31
 * and destruction code that works with placeholders must not assume
32
 * that the placeholder points to its out-of-flow.
33
 */
34
35
#ifndef nsPlaceholderFrame_h___
36
#define nsPlaceholderFrame_h___
37
38
#include "mozilla/Attributes.h"
39
#include "nsFrame.h"
40
#include "nsGkAtoms.h"
41
42
class nsPlaceholderFrame;
43
nsPlaceholderFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
44
                                           mozilla::ComputedStyle* aStyle,
45
                                           nsFrameState aTypeBits);
46
47
#define PLACEHOLDER_TYPE_MASK    (PLACEHOLDER_FOR_FLOAT | \
48
                                  PLACEHOLDER_FOR_ABSPOS | \
49
                                  PLACEHOLDER_FOR_FIXEDPOS | \
50
                                  PLACEHOLDER_FOR_POPUP | \
51
                                  PLACEHOLDER_FOR_TOPLAYER)
52
53
/**
54
 * Implementation of a frame that's used as a placeholder for a frame that
55
 * has been moved out of the flow.
56
 */
57
class nsPlaceholderFrame final : public nsFrame {
58
public:
59
  NS_DECL_FRAMEARENA_HELPERS(nsPlaceholderFrame)
60
#ifdef DEBUG
61
  NS_DECL_QUERYFRAME
62
#endif
63
64
  /**
65
   * Create a new placeholder frame.  aTypeBit must be one of the
66
   * PLACEHOLDER_FOR_* constants above.
67
   */
68
  friend nsPlaceholderFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
69
                                                    ComputedStyle* aStyle,
70
                                                    nsFrameState aTypeBits);
71
72
  nsPlaceholderFrame(ComputedStyle* aStyle, nsFrameState aTypeBits)
73
    : nsFrame(aStyle, kClassID)
74
    , mOutOfFlowFrame(nullptr)
75
0
  {
76
0
    MOZ_ASSERT(aTypeBits == PLACEHOLDER_FOR_FLOAT ||
77
0
               aTypeBits == PLACEHOLDER_FOR_ABSPOS ||
78
0
               aTypeBits == PLACEHOLDER_FOR_FIXEDPOS ||
79
0
               aTypeBits == PLACEHOLDER_FOR_POPUP ||
80
0
               aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_ABSPOS) ||
81
0
               aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_FIXEDPOS),
82
0
               "Unexpected type bit");
83
0
    AddStateBits(aTypeBits);
84
0
  }
85
86
  // Get/Set the associated out of flow frame
87
0
  nsIFrame*  GetOutOfFlowFrame() const { return mOutOfFlowFrame; }
88
0
  void       SetOutOfFlowFrame(nsIFrame* aFrame) {
89
0
               NS_ASSERTION(!aFrame || !aFrame->GetPrevContinuation(),
90
0
                            "OOF must be first continuation");
91
0
               mOutOfFlowFrame = aFrame;
92
0
             }
93
94
  // nsIFrame overrides
95
  // We need to override GetXULMinSize and GetXULPrefSize because XUL uses
96
  // placeholders not within lines.
97
  virtual void AddInlineMinISize(gfxContext* aRenderingContext,
98
                                 InlineMinISizeData* aData) override;
99
  virtual void AddInlinePrefISize(gfxContext* aRenderingContext,
100
                                  InlinePrefISizeData* aData) override;
101
  virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
102
  virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
103
  virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
104
105
  virtual void Reflow(nsPresContext* aPresContext,
106
                      ReflowOutput& aDesiredSize,
107
                      const ReflowInput& aReflowInput,
108
                      nsReflowStatus& aStatus) override;
109
110
  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
111
112
#if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF))
113
  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
114
                                const nsDisplayListSet& aLists) override;
115
#endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF)
116
117
#ifdef DEBUG_FRAME_DUMP
118
  void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const override;
119
  virtual nsresult GetFrameName(nsAString& aResult) const override;
120
#endif // DEBUG
121
122
0
  virtual bool IsEmpty() override { return true; }
123
0
  virtual bool IsSelfEmpty() override { return true; }
124
125
  virtual bool CanContinueTextRun() const override;
126
127
0
  void SetLineIsEmptySoFar(bool aValue) {
128
0
    AddOrRemoveStateBits(PLACEHOLDER_LINE_IS_EMPTY_SO_FAR, aValue);
129
0
    AddStateBits(PLACEHOLDER_HAVE_LINE_IS_EMPTY_SO_FAR);
130
0
  }
131
0
  bool GetLineIsEmptySoFar(bool* aResult) const {
132
0
    bool haveValue = HasAnyStateBits(PLACEHOLDER_HAVE_LINE_IS_EMPTY_SO_FAR);
133
0
    if (haveValue) {
134
0
      *aResult = HasAnyStateBits(PLACEHOLDER_LINE_IS_EMPTY_SO_FAR);
135
0
    }
136
0
    return haveValue;
137
0
  }
138
0
  void ForgetLineIsEmptySoFar() {
139
0
    RemoveStateBits(PLACEHOLDER_HAVE_LINE_IS_EMPTY_SO_FAR);
140
0
  }
141
142
#ifdef ACCESSIBILITY
143
  virtual mozilla::a11y::AccType AccessibleType() override
144
0
  {
145
0
    nsIFrame* realFrame = GetRealFrameForPlaceholder(this);
146
0
    return realFrame ? realFrame->AccessibleType() :
147
0
                       nsFrame::AccessibleType();
148
0
  }
149
#endif
150
151
  ComputedStyle* GetParentComputedStyleForOutOfFlow(nsIFrame** aProviderFrame) const;
152
153
  // Like GetParentComputedStyleForOutOfFlow, but ignores display:contents bits.
154
  ComputedStyle* GetLayoutParentStyleForOutOfFlow(nsIFrame** aProviderFrame) const;
155
156
  bool RenumberFrameAndDescendants(int32_t* aOrdinal,
157
                                   int32_t aDepth,
158
                                   int32_t aIncrement,
159
                                   bool aForCounting) override
160
0
  {
161
0
    return mOutOfFlowFrame->
162
0
      RenumberFrameAndDescendants(aOrdinal, aDepth, aIncrement, aForCounting);
163
0
  }
164
165
  /**
166
   * @return the out-of-flow for aFrame if aFrame is a placeholder; otherwise
167
   * aFrame
168
   */
169
0
  static nsIFrame* GetRealFrameFor(nsIFrame* aFrame) {
170
0
    MOZ_ASSERT(aFrame, "Must have a frame to work with");
171
0
    if (aFrame->IsPlaceholderFrame()) {
172
0
      return GetRealFrameForPlaceholder(aFrame);
173
0
    }
174
0
    return aFrame;
175
0
  }
176
177
  /**
178
   * @return the out-of-flow for aFrame, which is known to be a placeholder
179
   */
180
0
  static nsIFrame* GetRealFrameForPlaceholder(nsIFrame* aFrame) {
181
0
    MOZ_ASSERT(aFrame->IsPlaceholderFrame(),
182
0
               "Must have placeholder frame as input");
183
0
    nsIFrame* outOfFlow =
184
0
      static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame();
185
0
    NS_ASSERTION(outOfFlow, "Null out-of-flow for placeholder?");
186
0
    return outOfFlow;
187
0
  }
188
189
protected:
190
  nsIFrame* mOutOfFlowFrame;
191
};
192
193
#endif /* nsPlaceholderFrame_h___ */