Bug 1708422: part 13) Factor code out to `mozInlineSpellChecker::SpellCheckerTimeSlic...
[gecko.git] / layout / generic / nsIFrameInlines.h
blob6fc658e1d1bb863aad3c23d57a7802511473d375
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/. */
7 #ifndef nsIFrameInlines_h___
8 #define nsIFrameInlines_h___
10 #include "mozilla/dom/ElementInlines.h"
11 #include "nsContainerFrame.h"
12 #include "nsLayoutUtils.h"
13 #include "nsPlaceholderFrame.h"
14 #include "nsStyleStructInlines.h"
15 #include "nsCSSAnonBoxes.h"
16 #include "nsFrameManager.h"
18 bool nsIFrame::IsSVGGeometryFrameOrSubclass() const {
19 return IsSVGGeometryFrame() || IsSVGImageFrame();
22 bool nsIFrame::IsFlexItem() const {
23 return GetParent() && GetParent()->IsFlexContainerFrame() &&
24 !HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
27 bool nsIFrame::IsGridItem() const {
28 return GetParent() && GetParent()->IsGridContainerFrame() &&
29 !HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
32 bool nsIFrame::IsFlexOrGridContainer() const {
33 return IsFlexContainerFrame() || IsGridContainerFrame();
36 bool nsIFrame::IsFlexOrGridItem() const {
37 return !HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) && GetParent() &&
38 GetParent()->IsFlexOrGridContainer();
41 bool nsIFrame::IsMasonry(mozilla::LogicalAxis aAxis) const {
42 MOZ_DIAGNOSTIC_ASSERT(IsGridContainerFrame());
43 return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock
44 ? NS_STATE_GRID_IS_ROW_MASONRY
45 : NS_STATE_GRID_IS_COL_MASONRY);
48 bool nsIFrame::IsTableCaption() const {
49 return StyleDisplay()->mDisplay == mozilla::StyleDisplay::TableCaption &&
50 GetParent()->Style()->GetPseudoType() ==
51 mozilla::PseudoStyleType::tableWrapper;
54 bool nsIFrame::IsFloating() const {
55 return HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
56 StyleDisplay()->IsFloating(this);
59 bool nsIFrame::IsAbsPosContainingBlock() const {
60 return StyleDisplay()->IsAbsPosContainingBlock(this);
63 bool nsIFrame::IsFixedPosContainingBlock() const {
64 return StyleDisplay()->IsFixedPosContainingBlock(this);
67 bool nsIFrame::IsRelativelyPositioned() const {
68 return StyleDisplay()->IsRelativelyPositioned(this);
71 bool nsIFrame::IsStickyPositioned() const {
72 return StyleDisplay()->IsStickyPositioned(this);
75 bool nsIFrame::IsAbsolutelyPositioned(
76 const nsStyleDisplay* aStyleDisplay) const {
77 return HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
78 StyleDisplayWithOptionalParam(aStyleDisplay)
79 ->IsAbsolutelyPositioned(this);
82 inline bool nsIFrame::IsTrueOverflowContainer() const {
83 return HasAnyStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER) &&
84 !IsAbsolutelyPositioned();
85 // XXXfr This check isn't quite correct, because it doesn't handle cases
86 // where the out-of-flow has overflow.. but that's rare.
87 // We'll need to revisit the way abspos continuations are handled later
88 // for various reasons, this detail is one of them. See bug 154892
91 bool nsIFrame::IsBlockOutside() const {
92 return StyleDisplay()->IsBlockOutside(this);
95 bool nsIFrame::IsInlineOutside() const {
96 return StyleDisplay()->IsInlineOutside(this);
99 bool nsIFrame::IsColumnSpan() const {
100 return IsBlockOutside() && StyleColumn()->IsColumnSpanStyle();
103 bool nsIFrame::IsColumnSpanInMulticolSubtree() const {
104 return IsColumnSpan() &&
105 (HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) ||
106 // A frame other than inline and block won't have
107 // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR. We instead test its parent.
108 (GetParent() && GetParent()->Style()->GetPseudoType() ==
109 mozilla::PseudoStyleType::columnSpanWrapper));
112 mozilla::StyleDisplay nsIFrame::GetDisplay() const {
113 return StyleDisplay()->GetDisplay(this);
116 nscoord nsIFrame::SynthesizeBaselineBOffsetFromMarginBox(
117 mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const {
118 MOZ_ASSERT(!aWM.IsOrthogonalTo(GetWritingMode()));
119 auto margin = GetLogicalUsedMargin(aWM);
120 if (aGroup == BaselineSharingGroup::First) {
121 if (aWM.IsAlphabeticalBaseline()) {
122 // First baseline for inverted-line content is the block-start margin
123 // edge, as the frame is in effect "flipped" for alignment purposes.
124 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? -margin.BStart(aWM)
125 : BSize(aWM) + margin.BEnd(aWM);
127 nscoord marginBoxCenter = (BSize(aWM) + margin.BStartEnd(aWM)) / 2;
128 return marginBoxCenter - margin.BStart(aWM);
130 MOZ_ASSERT(aGroup == BaselineSharingGroup::Last);
131 if (aWM.IsAlphabeticalBaseline()) {
132 // Last baseline for inverted-line content is the block-start margin edge,
133 // as the frame is in effect "flipped" for alignment purposes.
134 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? BSize(aWM) + margin.BStart(aWM)
135 : -margin.BEnd(aWM);
137 // Round up for central baseline offset, to be consistent with ::First.
138 nscoord marginBoxSize = BSize(aWM) + margin.BStartEnd(aWM);
139 nscoord marginBoxCenter = (marginBoxSize / 2) + (marginBoxSize % 2);
140 return marginBoxCenter - margin.BEnd(aWM);
143 nscoord nsIFrame::SynthesizeBaselineBOffsetFromBorderBox(
144 mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const {
145 nscoord borderBoxSize = MOZ_UNLIKELY(aWM.IsOrthogonalTo(GetWritingMode()))
146 ? ISize(aWM)
147 : BSize(aWM);
148 if (aGroup == BaselineSharingGroup::First) {
149 return MOZ_LIKELY(aWM.IsAlphabeticalBaseline()) ? borderBoxSize
150 : borderBoxSize / 2;
152 MOZ_ASSERT(aGroup == BaselineSharingGroup::Last);
153 // Round up for central baseline offset, to be consistent with ::First.
154 auto borderBoxCenter = (borderBoxSize / 2) + (borderBoxSize % 2);
155 return MOZ_LIKELY(aWM.IsAlphabeticalBaseline()) ? 0 : borderBoxCenter;
158 nscoord nsIFrame::SynthesizeBaselineBOffsetFromContentBox(
159 mozilla::WritingMode aWM, BaselineSharingGroup aGroup) const {
160 mozilla::WritingMode wm = GetWritingMode();
161 MOZ_ASSERT(!aWM.IsOrthogonalTo(wm));
162 const auto bp = GetLogicalUsedBorderAndPadding(wm)
163 .ApplySkipSides(GetLogicalSkipSides())
164 .ConvertTo(aWM, wm);
166 if (MOZ_UNLIKELY(aWM.IsCentralBaseline())) {
167 nscoord contentBoxBSize = BSize(aWM) - bp.BStartEnd(aWM);
168 if (aGroup == BaselineSharingGroup::First) {
169 return contentBoxBSize / 2 + bp.BStart(aWM);
171 // Return the same center position as for ::First, but as offset from end:
172 nscoord halfContentBoxBSize = (contentBoxBSize / 2) + (contentBoxBSize % 2);
173 return halfContentBoxBSize + bp.BEnd(aWM);
175 if (aGroup == BaselineSharingGroup::First) {
176 // First baseline for inverted-line content is the block-start content
177 // edge, as the frame is in effect "flipped" for alignment purposes.
178 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? bp.BStart(aWM)
179 : BSize(aWM) - bp.BEnd(aWM);
181 // Last baseline for inverted-line content is the block-start content edge,
182 // as the frame is in effect "flipped" for alignment purposes.
183 return MOZ_UNLIKELY(aWM.IsLineInverted()) ? BSize(aWM) - bp.BStart(aWM)
184 : bp.BEnd(aWM);
187 nscoord nsIFrame::BaselineBOffset(mozilla::WritingMode aWM,
188 BaselineSharingGroup aBaselineGroup,
189 AlignmentContext aAlignmentContext) const {
190 MOZ_ASSERT(!aWM.IsOrthogonalTo(GetWritingMode()));
191 nscoord baseline;
192 if (GetNaturalBaselineBOffset(aWM, aBaselineGroup, &baseline)) {
193 return baseline;
195 if (aAlignmentContext == AlignmentContext::Inline) {
196 return SynthesizeBaselineBOffsetFromMarginBox(aWM, aBaselineGroup);
198 if (aAlignmentContext == AlignmentContext::Table) {
199 return SynthesizeBaselineBOffsetFromContentBox(aWM, aBaselineGroup);
201 return SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup);
204 void nsIFrame::PropagateWritingModeToSelfAndAncestors(
205 mozilla::WritingMode aWM) {
206 MOZ_ASSERT(IsCanvasFrame());
207 for (auto f = this; f; f = f->GetParent()) {
208 f->mWritingMode = aWM;
212 nsContainerFrame* nsIFrame::GetInFlowParent() const {
213 if (HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
214 nsIFrame* ph =
215 FirstContinuation()->GetProperty(nsIFrame::PlaceholderFrameProperty());
216 return ph->GetParent();
219 return GetParent();
222 // We generally want to follow the style tree for preserve-3d, jumping through
223 // display: contents.
225 // There are various fun mismatches between the flattened tree and the frame
226 // tree which makes this non-trivial to do looking at the frame tree state:
228 // - Anon boxes. You'd have to step through them, because you generally want to
229 // ignore them.
231 // - IB-splits, which produce a frame tree where frames for the block inside
232 // the inline are not children of any frame from the inline.
234 // - display: contents, which makes DOM ancestors not have frames even when a
235 // descendant does.
237 // See GetFlattenedTreeParentElementForStyle for the difference between it and
238 // plain GetFlattenedTreeParentElement.
239 nsIFrame* nsIFrame::GetClosestFlattenedTreeAncestorPrimaryFrame() const {
240 if (!mContent) {
241 return nullptr;
243 mozilla::dom::Element* parent =
244 mContent->GetFlattenedTreeParentElementForStyle();
245 while (parent) {
246 if (nsIFrame* frame = parent->GetPrimaryFrame()) {
247 return frame;
249 // NOTE(emilio): This should be an assert except we have code in tree which
250 // violates invariants like the <frameset> frame construction code.
251 if (MOZ_UNLIKELY(!parent->IsDisplayContents())) {
252 return nullptr;
254 parent = parent->GetFlattenedTreeParentElementForStyle();
256 return nullptr;
259 nsPoint nsIFrame::GetNormalPosition(bool* aHasProperty) const {
260 nsPoint* normalPosition = GetProperty(NormalPositionProperty());
261 if (normalPosition) {
262 if (aHasProperty) {
263 *aHasProperty = true;
265 return *normalPosition;
267 if (aHasProperty) {
268 *aHasProperty = false;
270 return GetPosition();
273 mozilla::LogicalPoint nsIFrame::GetLogicalNormalPosition(
274 mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const {
275 // Subtract the size of this frame from the container size to get
276 // the correct position in rtl frames where the origin is on the
277 // right instead of the left
278 return mozilla::LogicalPoint(aWritingMode, GetNormalPosition(),
279 aContainerSize - mRect.Size());
282 #endif