nsPlaceholderFrame.h (7161B)
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 "nsGkAtoms.h" 39 #include "nsIFrame.h" 40 41 namespace mozilla { 42 class PresShell; 43 } // namespace mozilla 44 45 class nsPlaceholderFrame; 46 nsPlaceholderFrame* NS_NewPlaceholderFrame(mozilla::PresShell* aPresShell, 47 mozilla::ComputedStyle* aStyle, 48 nsFrameState aTypeBits); 49 50 #define PLACEHOLDER_TYPE_MASK \ 51 (PLACEHOLDER_FOR_FLOAT | PLACEHOLDER_FOR_ABSPOS | PLACEHOLDER_FOR_FIXEDPOS | \ 52 PLACEHOLDER_FOR_TOPLAYER) 53 54 /** 55 * Implementation of a frame that's used as a placeholder for a frame that 56 * has been moved out of the flow. 57 */ 58 class nsPlaceholderFrame final : public nsIFrame { 59 public: 60 NS_DECL_FRAMEARENA_HELPERS(nsPlaceholderFrame) 61 #ifdef DEBUG 62 NS_DECL_QUERYFRAME 63 #endif 64 65 /** 66 * Create a new placeholder frame. aTypeBit must be one of the 67 * PLACEHOLDER_FOR_* constants above. 68 */ 69 friend nsPlaceholderFrame* NS_NewPlaceholderFrame( 70 mozilla::PresShell* aPresShell, ComputedStyle* aStyle, 71 nsFrameState aTypeBits); 72 73 nsPlaceholderFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, 74 nsFrameState aTypeBits) 75 : nsIFrame(aStyle, aPresContext, kClassID), mOutOfFlowFrame(nullptr) { 76 MOZ_ASSERT( 77 aTypeBits == PLACEHOLDER_FOR_FLOAT || 78 aTypeBits == PLACEHOLDER_FOR_ABSPOS || 79 aTypeBits == PLACEHOLDER_FOR_FIXEDPOS || 80 aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_ABSPOS) || 81 aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_FIXEDPOS), 82 "Unexpected type bit"); 83 AddStateBits(aTypeBits); 84 } 85 86 // Get/Set the associated out of flow frame 87 nsIFrame* GetOutOfFlowFrame() const { return mOutOfFlowFrame; } 88 void SetOutOfFlowFrame(nsIFrame* aFrame) { 89 NS_ASSERTION(!aFrame || !aFrame->GetPrevContinuation(), 90 "OOF must be first continuation"); 91 mOutOfFlowFrame = aFrame; 92 } 93 94 void AddInlineMinISize(const mozilla::IntrinsicSizeInput& aInput, 95 InlineMinISizeData* aData) override; 96 void AddInlinePrefISize(const mozilla::IntrinsicSizeInput& aInput, 97 InlinePrefISizeData* aData) override; 98 99 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, 100 const ReflowInput& aReflowInput, 101 nsReflowStatus& aStatus) override; 102 103 void Destroy(DestroyContext&) override; 104 105 #if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)) 106 void BuildDisplayList(nsDisplayListBuilder* aBuilder, 107 const nsDisplayListSet& aLists) override; 108 #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF) 109 110 #ifdef DEBUG_FRAME_DUMP 111 void List(FILE* out = stderr, const char* aPrefix = "", 112 ListFlags aFlags = ListFlags()) const override; 113 nsresult GetFrameName(nsAString& aResult) const override; 114 #endif // DEBUG 115 116 bool IsEmpty() override { return true; } 117 bool IsSelfEmpty() override { return true; } 118 119 bool CanContinueTextRun() const override; 120 121 void SetLineIsEmptySoFar(bool aValue) { 122 AddOrRemoveStateBits(PLACEHOLDER_LINE_IS_EMPTY_SO_FAR, aValue); 123 AddStateBits(PLACEHOLDER_HAVE_LINE_IS_EMPTY_SO_FAR); 124 } 125 bool GetLineIsEmptySoFar(bool* aResult) const { 126 bool haveValue = HasAnyStateBits(PLACEHOLDER_HAVE_LINE_IS_EMPTY_SO_FAR); 127 if (haveValue) { 128 *aResult = HasAnyStateBits(PLACEHOLDER_LINE_IS_EMPTY_SO_FAR); 129 } 130 return haveValue; 131 } 132 void ForgetLineIsEmptySoFar() { 133 RemoveStateBits(PLACEHOLDER_HAVE_LINE_IS_EMPTY_SO_FAR); 134 } 135 136 #ifdef ACCESSIBILITY 137 mozilla::a11y::AccType AccessibleType() override { 138 nsIFrame* realFrame = GetRealFrameForPlaceholder(this); 139 return realFrame ? realFrame->AccessibleType() : nsIFrame::AccessibleType(); 140 } 141 #endif 142 143 ComputedStyle* GetParentComputedStyleForOutOfFlow( 144 nsIFrame** aProviderFrame) const; 145 146 // Like GetParentComputedStyleForOutOfFlow, but ignores display:contents bits. 147 ComputedStyle* GetLayoutParentStyleForOutOfFlow( 148 nsIFrame** aProviderFrame) const; 149 150 bool RenumberFrameAndDescendants(int32_t* aOrdinal, int32_t aDepth, 151 int32_t aIncrement, 152 bool aForCounting) override { 153 return mOutOfFlowFrame->RenumberFrameAndDescendants( 154 aOrdinal, aDepth, aIncrement, aForCounting); 155 } 156 157 /** 158 * @return the out-of-flow for aFrame if aFrame is a placeholder; otherwise 159 * aFrame 160 */ 161 static nsIFrame* GetRealFrameFor(nsIFrame* aFrame) { 162 MOZ_ASSERT(aFrame, "Must have a frame to work with"); 163 if (aFrame->IsPlaceholderFrame()) { 164 return GetRealFrameForPlaceholder(aFrame); 165 } 166 return aFrame; 167 } 168 169 /** 170 * @return the out-of-flow for aFrame, which is known to be a placeholder 171 */ 172 static nsIFrame* GetRealFrameForPlaceholder(const nsIFrame* aFrame) { 173 MOZ_ASSERT(aFrame->IsPlaceholderFrame(), 174 "Must have placeholder frame as input"); 175 nsIFrame* outOfFlow = 176 static_cast<const nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame(); 177 NS_ASSERTION(outOfFlow, "Null out-of-flow for placeholder?"); 178 return outOfFlow; 179 } 180 181 protected: 182 // A helper to implement AddInlineMinISize() and AddInlinePrefISize(). 183 void AddFloatToIntrinsicISizeData(const mozilla::IntrinsicSizeInput& aInput, 184 mozilla::IntrinsicISizeType aType, 185 InlineIntrinsicISizeData* aData) const; 186 187 nsIFrame* mOutOfFlowFrame; 188 }; 189 190 #endif /* nsPlaceholderFrame_h___ */