fune/layout/generic/nsContainerFrameInlines.h
Xidorn Quan 91de536124 Bug 1696721 part 2 - Refactor DoIntrinsicInlineISize to make it accept a function for handling children. r=dholbert
While nsInlineFrame and nsFirstLetterFrame are going to continue sharing the same code, nsRubyFrame will use the refactored version to compute its intrinsic sizes.

This way we can also eliminate the need for checking the intrinsic type inside the function.

This patch shouldn't change behavior. It's just a refactoring of existing code.

Differential Revision: https://phabricator.services.mozilla.com/D109227
2021-03-23 10:26:17 +00:00

118 lines
4.1 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsContainerFrameInlines_h___
#define nsContainerFrameInlines_h___
#include "nsContainerFrame.h"
namespace mozilla {
namespace detail {
static nscoord GetCoord(const LengthPercentage& aCoord, nscoord aIfNotCoord) {
if (aCoord.ConvertsToLength()) {
return aCoord.ToLength();
}
return aIfNotCoord;
}
static nscoord GetCoord(const LengthPercentageOrAuto& aCoord,
nscoord aIfNotCoord) {
if (aCoord.IsAuto()) {
return aIfNotCoord;
}
return GetCoord(aCoord.AsLengthPercentage(), aIfNotCoord);
}
} // namespace detail
} // namespace mozilla
template <typename ISizeData, typename F>
void nsContainerFrame::DoInlineIntrinsicISize(ISizeData* aData,
F& aHandleChildren) {
using namespace mozilla;
using mozilla::detail::GetCoord;
if (GetPrevInFlow()) return; // Already added.
WritingMode wm = GetWritingMode();
Side startSide = wm.PhysicalSideForInlineAxis(eLogicalEdgeStart);
Side endSide = wm.PhysicalSideForInlineAxis(eLogicalEdgeEnd);
const nsStylePadding* stylePadding = StylePadding();
const nsStyleBorder* styleBorder = StyleBorder();
const nsStyleMargin* styleMargin = StyleMargin();
// This goes at the beginning no matter how things are broken and how
// messy the bidi situations are, since per CSS2.1 section 8.6
// (implemented in bug 328168), the startSide border is always on the
// first line.
// This frame is a first-in-flow, but it might have a previous bidi
// continuation, in which case that continuation should handle the startSide
// border.
// For box-decoration-break:clone we setup clonePBM = startPBM + endPBM and
// add that to each line. For box-decoration-break:slice clonePBM is zero.
nscoord clonePBM = 0; // PBM = PaddingBorderMargin
const bool sliceBreak =
styleBorder->mBoxDecorationBreak == StyleBoxDecorationBreak::Slice;
if (!GetPrevContinuation() || MOZ_UNLIKELY(!sliceBreak)) {
nscoord startPBM =
// clamp negative calc() to 0
std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
styleBorder->GetComputedBorderWidth(startSide) +
GetCoord(styleMargin->mMargin.Get(startSide), 0);
if (MOZ_LIKELY(sliceBreak)) {
aData->mCurrentLine += startPBM;
} else {
clonePBM = startPBM;
}
}
nscoord endPBM =
// clamp negative calc() to 0
std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
styleBorder->GetComputedBorderWidth(endSide) +
GetCoord(styleMargin->mMargin.Get(endSide), 0);
if (MOZ_UNLIKELY(!sliceBreak)) {
clonePBM += endPBM;
aData->mCurrentLine += clonePBM;
}
const nsLineList_iterator* savedLine = aData->mLine;
nsIFrame* const savedLineContainer = aData->LineContainer();
nsContainerFrame* lastInFlow;
for (nsContainerFrame* nif = this; nif;
nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
if (aData->mCurrentLine == 0) {
aData->mCurrentLine = clonePBM;
}
aHandleChildren(nif, aData);
// After we advance to our next-in-flow, the stored line and line container
// may no longer be correct. Just forget them.
aData->mLine = nullptr;
aData->SetLineContainer(nullptr);
lastInFlow = nif;
}
aData->mLine = savedLine;
aData->SetLineContainer(savedLineContainer);
// This goes at the end no matter how things are broken and how
// messy the bidi situations are, since per CSS2.1 section 8.6
// (implemented in bug 328168), the endSide border is always on the
// last line.
// We reached the last-in-flow, but it might have a next bidi
// continuation, in which case that continuation should handle
// the endSide border.
if (MOZ_LIKELY(!lastInFlow->GetNextContinuation() && sliceBreak)) {
aData->mCurrentLine += endPBM;
}
}
#endif // nsContainerFrameInlines_h___