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