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 #ifndef nsIFrameInlines_h___
8 #define nsIFrameInlines_h___
9
10 #include "mozilla/dom/ElementInlines.h"
11 #include "nsContainerFrame.h"
12 #include "nsPlaceholderFrame.h"
13 #include "nsStyleStructInlines.h"
14 #include "nsCSSAnonBoxes.h"
15 #include "nsFrameManager.h"
16
IsSVGGeometryFrameOrSubclass()17 bool nsIFrame::IsSVGGeometryFrameOrSubclass() const {
18 return IsSVGGeometryFrame() || IsSVGImageFrame();
19 }
20
IsFlexItem()21 bool nsIFrame::IsFlexItem() const {
22 return GetParent() && GetParent()->IsFlexContainerFrame() &&
23 !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
24 }
25
IsGridItem()26 bool nsIFrame::IsGridItem() const {
27 return GetParent() && GetParent()->IsGridContainerFrame() &&
28 !(GetStateBits() & NS_FRAME_OUT_OF_FLOW);
29 }
30
IsFlexOrGridContainer()31 bool nsIFrame::IsFlexOrGridContainer() const {
32 return IsFlexContainerFrame() || IsGridContainerFrame();
33 }
34
IsFlexOrGridItem()35 bool nsIFrame::IsFlexOrGridItem() const {
36 return !(GetStateBits() & NS_FRAME_OUT_OF_FLOW) && GetParent() &&
37 GetParent()->IsFlexOrGridContainer();
38 }
39
IsMasonry(mozilla::LogicalAxis aAxis)40 bool nsIFrame::IsMasonry(mozilla::LogicalAxis aAxis) const {
41 MOZ_DIAGNOSTIC_ASSERT(IsGridContainerFrame());
42 return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock
43 ? NS_STATE_GRID_IS_ROW_MASONRY
44 : NS_STATE_GRID_IS_COL_MASONRY);
45 }
46
IsTableCaption()47 bool nsIFrame::IsTableCaption() const {
48 return StyleDisplay()->mDisplay == mozilla::StyleDisplay::TableCaption &&
49 GetParent()->Style()->GetPseudoType() ==
50 mozilla::PseudoStyleType::tableWrapper;
51 }
52
IsFloating()53 bool nsIFrame::IsFloating() const { return StyleDisplay()->IsFloating(this); }
54
IsAbsPosContainingBlock()55 bool nsIFrame::IsAbsPosContainingBlock() const {
56 return StyleDisplay()->IsAbsPosContainingBlock(this);
57 }
58
IsFixedPosContainingBlock()59 bool nsIFrame::IsFixedPosContainingBlock() const {
60 return StyleDisplay()->IsFixedPosContainingBlock(this);
61 }
62
IsRelativelyPositioned()63 bool nsIFrame::IsRelativelyPositioned() const {
64 return StyleDisplay()->IsRelativelyPositioned(this);
65 }
66
IsStickyPositioned()67 bool nsIFrame::IsStickyPositioned() const {
68 return StyleDisplay()->IsStickyPositioned(this);
69 }
70
IsAbsolutelyPositioned(const nsStyleDisplay * aStyleDisplay)71 bool nsIFrame::IsAbsolutelyPositioned(
72 const nsStyleDisplay* aStyleDisplay) const {
73 const nsStyleDisplay* disp = StyleDisplayWithOptionalParam(aStyleDisplay);
74 return disp->IsAbsolutelyPositioned(this);
75 }
76
IsBlockOutside()77 bool nsIFrame::IsBlockOutside() const {
78 return StyleDisplay()->IsBlockOutside(this);
79 }
80
IsInlineOutside()81 bool nsIFrame::IsInlineOutside() const {
82 return StyleDisplay()->IsInlineOutside(this);
83 }
84
IsColumnSpan()85 bool nsIFrame::IsColumnSpan() const {
86 return IsBlockOutside() && StyleColumn()->IsColumnSpanStyle();
87 }
88
IsColumnSpanInMulticolSubtree()89 bool nsIFrame::IsColumnSpanInMulticolSubtree() const {
90 return IsColumnSpan() &&
91 (HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) ||
92 // A frame other than inline and block won't have
93 // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR. We instead test its parent.
94 (GetParent() && GetParent()->Style()->GetPseudoType() ==
95 mozilla::PseudoStyleType::columnSpanWrapper));
96 }
97
GetDisplay()98 mozilla::StyleDisplay nsIFrame::GetDisplay() const {
99 return StyleDisplay()->GetDisplay(this);
100 }
101
SynthesizeBaselineBOffsetFromMarginBox(mozilla::WritingMode aWM,BaselineSharingGroup aGroup)102 nscoord nsIFrame::SynthesizeBaselineBOffsetFromMarginBox(
103 mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const {
104 MOZ_ASSERT(!aWM.IsOrthogonalTo(GetWritingMode()));
105 auto margin = GetLogicalUsedMargin(aWM);
106 if (aGroup == BaselineSharingGroup::First) {
107 if (aWM.IsAlphabeticalBaseline()) {
108 // First baseline for inverted-line content is the block-start margin
109 // edge, as the frame is in effect "flipped" for alignment purposes.
110 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? -margin.BStart(aWM)
111 : BSize(aWM) + margin.BEnd(aWM);
112 }
113 nscoord marginBoxCenter = (BSize(aWM) + margin.BStartEnd(aWM)) / 2;
114 return marginBoxCenter - margin.BStart(aWM);
115 }
116 MOZ_ASSERT(aGroup == BaselineSharingGroup::Last);
117 if (aWM.IsAlphabeticalBaseline()) {
118 // Last baseline for inverted-line content is the block-start margin edge,
119 // as the frame is in effect "flipped" for alignment purposes.
120 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? BSize(aWM) + margin.BStart(aWM)
121 : -margin.BEnd(aWM);
122 }
123 // Round up for central baseline offset, to be consistent with ::First.
124 nscoord marginBoxSize = BSize(aWM) + margin.BStartEnd(aWM);
125 nscoord marginBoxCenter = (marginBoxSize / 2) + (marginBoxSize % 2);
126 return marginBoxCenter - margin.BEnd(aWM);
127 }
128
SynthesizeBaselineBOffsetFromBorderBox(mozilla::WritingMode aWM,BaselineSharingGroup aGroup)129 nscoord nsIFrame::SynthesizeBaselineBOffsetFromBorderBox(
130 mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const {
131 MOZ_ASSERT(!aWM.IsOrthogonalTo(GetWritingMode()));
132 nscoord borderBoxSize = BSize(aWM);
133 if (aGroup == BaselineSharingGroup::First) {
134 return MOZ_LIKELY(aWM.IsAlphabeticalBaseline()) ? borderBoxSize
135 : borderBoxSize / 2;
136 }
137 MOZ_ASSERT(aGroup == BaselineSharingGroup::Last);
138 // Round up for central baseline offset, to be consistent with ::First.
139 auto borderBoxCenter = (borderBoxSize / 2) + (borderBoxSize % 2);
140 return MOZ_LIKELY(aWM.IsAlphabeticalBaseline()) ? 0 : borderBoxCenter;
141 }
142
SynthesizeBaselineBOffsetFromContentBox(mozilla::WritingMode aWM,BaselineSharingGroup aGroup)143 nscoord nsIFrame::SynthesizeBaselineBOffsetFromContentBox(
144 mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const {
145 mozilla::WritingMode wm = GetWritingMode();
146 MOZ_ASSERT(!aWM.IsOrthogonalTo(wm));
147 const auto bp = GetLogicalUsedBorderAndPadding(wm)
148 .ApplySkipSides(GetLogicalSkipSides())
149 .ConvertTo(aWM, wm);
150
151 if (MOZ_UNLIKELY(aWM.IsCentralBaseline())) {
152 nscoord contentBoxBSize = BSize(aWM) - bp.BStartEnd(aWM);
153 if (aGroup == BaselineSharingGroup::First) {
154 return contentBoxBSize / 2 + bp.BStart(aWM);
155 }
156 // Return the same center position as for ::First, but as offset from end:
157 nscoord halfContentBoxBSize = (contentBoxBSize / 2) + (contentBoxBSize % 2);
158 return halfContentBoxBSize + bp.BEnd(aWM);
159 }
160 if (aGroup == BaselineSharingGroup::First) {
161 // First baseline for inverted-line content is the block-start content
162 // edge, as the frame is in effect "flipped" for alignment purposes.
163 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? bp.BStart(aWM)
164 : BSize(aWM) - bp.BEnd(aWM);
165 }
166 // Last baseline for inverted-line content is the block-start content edge,
167 // as the frame is in effect "flipped" for alignment purposes.
168 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? BSize(aWM) - bp.BStart(aWM)
169 : bp.BEnd(aWM);
170 }
171
BaselineBOffset(mozilla::WritingMode aWM,BaselineSharingGroup aBaselineGroup,AlignmentContext aAlignmentContext)172 nscoord nsIFrame::BaselineBOffset(mozilla::WritingMode aWM,
173 BaselineSharingGroup aBaselineGroup,
174 AlignmentContext aAlignmentContext) const {
175 MOZ_ASSERT(!aWM.IsOrthogonalTo(GetWritingMode()));
176 nscoord baseline;
177 if (GetNaturalBaselineBOffset(aWM, aBaselineGroup, &baseline)) {
178 return baseline;
179 }
180 if (aAlignmentContext == AlignmentContext::Inline) {
181 return SynthesizeBaselineBOffsetFromMarginBox(aWM, aBaselineGroup);
182 }
183 if (aAlignmentContext == AlignmentContext::Table) {
184 return SynthesizeBaselineBOffsetFromContentBox(aWM, aBaselineGroup);
185 }
186 return SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup);
187 }
188
PropagateWritingModeToSelfAndAncestors(mozilla::WritingMode aWM)189 void nsIFrame::PropagateWritingModeToSelfAndAncestors(
190 mozilla::WritingMode aWM) {
191 MOZ_ASSERT(IsCanvasFrame());
192 for (auto f = this; f; f = f->GetParent()) {
193 f->mWritingMode = aWM;
194 }
195 }
196
GetInFlowParent()197 nsContainerFrame* nsIFrame::GetInFlowParent() const {
198 if (GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
199 nsIFrame* ph =
200 FirstContinuation()->GetProperty(nsIFrame::PlaceholderFrameProperty());
201 return ph->GetParent();
202 }
203
204 return GetParent();
205 }
206
207 // We generally want to follow the style tree for preserve-3d, jumping through
208 // display: contents.
209 //
210 // There are various fun mismatches between the flattened tree and the frame
211 // tree which makes this non-trivial to do looking at the frame tree state:
212 //
213 // - Anon boxes. You'd have to step through them, because you generally want to
214 // ignore them.
215 //
216 // - IB-splits, which produce a frame tree where frames for the block inside
217 // the inline are not children of any frame from the inline.
218 //
219 // - display: contents, which makes DOM ancestors not have frames even when a
220 // descendant does.
221 //
222 // See GetFlattenedTreeParentElementForStyle for the difference between it and
223 // plain GetFlattenedTreeParentElement.
GetClosestFlattenedTreeAncestorPrimaryFrame()224 nsIFrame* nsIFrame::GetClosestFlattenedTreeAncestorPrimaryFrame() const {
225 if (!mContent) {
226 return nullptr;
227 }
228 mozilla::dom::Element* parent =
229 mContent->GetFlattenedTreeParentElementForStyle();
230 while (parent) {
231 if (nsIFrame* frame = parent->GetPrimaryFrame()) {
232 return frame;
233 }
234 // NOTE(emilio): This should be an assert except we have code in tree which
235 // violates invariants like the <frameset> frame construction code.
236 if (MOZ_UNLIKELY(!parent->IsDisplayContents())) {
237 return nullptr;
238 }
239 parent = parent->GetFlattenedTreeParentElementForStyle();
240 }
241 return nullptr;
242 }
243
GetNormalPosition(bool * aHasProperty)244 nsPoint nsIFrame::GetNormalPosition(bool* aHasProperty) const {
245 nsPoint* normalPosition = GetProperty(NormalPositionProperty());
246 if (normalPosition) {
247 if (aHasProperty) {
248 *aHasProperty = true;
249 }
250 return *normalPosition;
251 }
252 if (aHasProperty) {
253 *aHasProperty = false;
254 }
255 return GetPosition();
256 }
257
GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,const nsSize & aContainerSize)258 mozilla::LogicalPoint nsIFrame::GetLogicalNormalPosition(
259 mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const {
260 // Subtract the size of this frame from the container size to get
261 // the correct position in rtl frames where the origin is on the
262 // right instead of the left
263 return mozilla::LogicalPoint(aWritingMode, GetNormalPosition(),
264 aContainerSize - mRect.Size());
265 }
266
267 #endif
268