Bug 1740580 - Align shrink-wrap behavior of semi-replaced elements with the spec. r=dholbert,layout-reviewers

The removed reftsts test basically the opposite, and are sufficiently
covered by the WPTs that we start passing, so just remove them.

Differential Revision: https://phabricator.services.mozilla.com/D204797
This commit is contained in:
Emilio Cobos Álvarez 2024-03-23 15:14:20 +00:00
parent 1bdebc4440
commit ec751e23e0
25 changed files with 324 additions and 711 deletions

View File

@ -37,16 +37,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=502258
element.type = "text";
await new Promise(resolve => requestAnimationFrame(resolve));
var typeTextSnapshot = await snapshotWindow(window);
results = compareSnapshots(baseSnapshot, typeTextSnapshot, true);
ok(results[0], aId + ": type=text should render the same as type=password that is showing the password");
info(aId + ": type=text should render the same as type=password that is showing the password");
assertSnapshots(baseSnapshot, typeTextSnapshot, true, null, aId + ": base", aId + ": type=text");
// Re-setting value shouldn't change anything.
// eslint-disable-next-line no-self-assign
element.value = element.value;
var tmpSnapshot = await snapshotWindow(window);
results = compareSnapshots(baseSnapshot, tmpSnapshot, true);
ok(results[0], aId + ": re-setting the value should change nothing");
info(aId + ": re-setting the value should change nothing");
assertSnapshots(baseSnapshot, tmpSnapshot, true, null, aId + ": base", aId + ": tmp");
}
async function reset_show_password(aId, concealedSnapshot) {
@ -54,8 +54,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=502258
element.type = "password";
await new Promise(resolve => requestAnimationFrame(resolve));
var typePasswordSnapshot = await snapshotWindow(window);
results = compareSnapshots(concealedSnapshot, typePasswordSnapshot, true);
ok(results[0], aId + ": changing the type attribute should conceal the password again");
info(aId + ": changing the type attribute should conceal the password again");
assertSnapshots(concealedSnapshot, typePasswordSnapshot, true, null, aId + ": concealed", aId + ": type=password");
}
async function runTest() {

View File

@ -76,13 +76,9 @@ LogicalSize nsCheckboxRadioFrame::ComputeAutoSize(
if (!StyleDisplay()->HasAppearance()) {
return size;
}
// Note: this call always set the BSize to NS_UNCONSTRAINEDSIZE.
size = nsAtomicContainerFrame::ComputeAutoSize(
return nsAtomicContainerFrame::ComputeAutoSize(
aRC, aWM, aCBSize, aAvailableISize, aMargin, aBorderPadding,
aSizeOverrides, aFlags);
size.BSize(aWM) = DefaultSize();
return size;
}
Maybe<nscoord> nsCheckboxRadioFrame::GetNaturalBaselineBOffset(
@ -133,10 +129,13 @@ void nsCheckboxRadioFrame::Reflow(nsPresContext* aPresContext,
aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
const auto wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
const auto contentBoxSize =
aReflowInput.ComputedSizeWithBSizeFallback([&] { return DefaultSize(); });
aDesiredSize.SetSize(
wm,
contentBoxSize + aReflowInput.ComputedLogicalBorderPadding(wm).Size(wm));
if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
const float inflation = nsLayoutUtils::FontSizeInflationFor(this);
aDesiredSize.Width() *= inflation;
aDesiredSize.Height() *= inflation;
}

View File

@ -93,13 +93,19 @@ void nsMeterFrame::Reflow(nsPresContext* aPresContext,
nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
NS_ASSERTION(barFrame, "The meter frame should have a child with a frame!");
ReflowBarFrame(barFrame, aPresContext, aReflowInput, aStatus);
const auto wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
const auto contentBoxSize = aReflowInput.ComputedSizeWithBSizeFallback([&] {
nscoord em = OneEmInAppUnits();
return ResolvedOrientationIsVertical() == wm.IsVertical() ? em : 5 * em;
});
aDesiredSize.SetSize(
wm,
contentBoxSize + aReflowInput.ComputedLogicalBorderPadding(wm).Size(wm));
aDesiredSize.SetOverflowAreasToDesiredBounds();
ReflowBarFrame(barFrame, aPresContext, aReflowInput, contentBoxSize, aStatus);
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
FinishAndStoreOverflow(&aDesiredSize);
aStatus.Reset(); // This type of frame can't be split.
@ -108,14 +114,19 @@ void nsMeterFrame::Reflow(nsPresContext* aPresContext,
void nsMeterFrame::ReflowBarFrame(nsIFrame* aBarFrame,
nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
const LogicalSize& aParentContentBoxSize,
nsReflowStatus& aStatus) {
bool vertical = ResolvedOrientationIsVertical();
WritingMode wm = aBarFrame->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSize(wm);
const WritingMode wm = aBarFrame->GetWritingMode();
const LogicalSize parentSizeInChildWM =
aParentContentBoxSize.ConvertTo(wm, aReflowInput.GetWritingMode());
const nsSize parentPhysicalSize = parentSizeInChildWM.GetPhysicalSize(wm);
LogicalSize availSize = parentSizeInChildWM;
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput reflowInput(aPresContext, aReflowInput, aBarFrame, availSize);
ReflowInput reflowInput(aPresContext, aReflowInput, aBarFrame, availSize,
Some(parentSizeInChildWM));
nscoord size =
vertical ? aReflowInput.ComputedHeight() : aReflowInput.ComputedWidth();
vertical ? parentPhysicalSize.Height() : parentPhysicalSize.Width();
nscoord xoffset = aReflowInput.ComputedPhysicalBorderPadding().left;
nscoord yoffset = aReflowInput.ComputedPhysicalBorderPadding().top;
@ -123,14 +134,13 @@ void nsMeterFrame::ReflowBarFrame(nsIFrame* aBarFrame,
size = NSToCoordRound(size * meterElement->Position());
if (!vertical && wm.IsPhysicalRTL()) {
xoffset += aReflowInput.ComputedWidth() - size;
xoffset += parentPhysicalSize.Width() - size;
}
// The bar position is *always* constrained.
if (vertical) {
// We want the bar to begin at the bottom.
yoffset += aReflowInput.ComputedHeight() - size;
yoffset += parentPhysicalSize.Height() - size;
size -= reflowInput.ComputedPhysicalMargin().TopBottom() +
reflowInput.ComputedPhysicalBorderPadding().TopBottom();
size = std::max(size, 0);
@ -169,39 +179,12 @@ nsresult nsMeterFrame::AttributeChanged(int32_t aNameSpaceID,
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
}
LogicalSize nsMeterFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);
autoSize.BSize(wm) = autoSize.ISize(wm) =
fontMet->Font().size.ToAppUnits(); // 1em
if (ResolvedOrientationIsVertical() == wm.IsVertical()) {
autoSize.ISize(wm) *= 5; // 5em
} else {
autoSize.BSize(wm) *= 5; // 5em
}
return autoSize.ConvertTo(aWM, wm);
}
nscoord nsMeterFrame::GetMinISize(gfxContext* aRenderingContext) {
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
nscoord minISize = fontMet->Font().size.ToAppUnits(); // 1em
nscoord minISize = OneEmInAppUnits();
if (ResolvedOrientationIsVertical() == GetWritingMode().IsVertical()) {
// The orientation is inline
minISize *= 5; // 5em
minISize *= 5;
}
return minISize;
}

View File

@ -7,17 +7,15 @@
#ifndef nsMeterFrame_h___
#define nsMeterFrame_h___
#include "mozilla/Attributes.h"
#include "nsContainerFrame.h"
#include "nsIAnonymousContentCreator.h"
#include "nsCOMPtr.h"
#include "nsCSSPseudoElements.h"
class nsMeterFrame final : public nsContainerFrame,
public nsIAnonymousContentCreator
{
typedef mozilla::dom::Element Element;
using Element = mozilla::dom::Element;
public:
NS_DECL_QUERYFRAME
@ -27,36 +25,25 @@ class nsMeterFrame final : public nsContainerFrame,
virtual ~nsMeterFrame();
void Destroy(DestroyContext&) override;
virtual void Reflow(nsPresContext* aCX, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void Reflow(nsPresContext*, ReflowOutput&, const ReflowInput&,
nsReflowStatus&) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(u"Meter"_ns, aResult);
}
#endif
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(
nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
virtual mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
nscoord GetMinISize(gfxContext* aRenderingContext) override;
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
/**
* Returns whether the frame and its child should use the native style.
@ -66,7 +53,9 @@ class nsMeterFrame final : public nsContainerFrame,
protected:
// Helper function which reflow the anonymous div frame.
void ReflowBarFrame(nsIFrame* aBarFrame, nsPresContext* aPresContext,
const ReflowInput& aReflowInput, nsReflowStatus& aStatus);
const ReflowInput& aReflowInput,
const mozilla::LogicalSize& aParentContentBoxSize,
nsReflowStatus& aStatus);
/**
* The div used to show the meter bar.
* @see nsMeterFrame::CreateAnonymousContent

View File

@ -99,11 +99,18 @@ void nsProgressFrame::Reflow(nsPresContext* aPresContext,
"need to call RegUnregAccessKey only for the first.");
const auto wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
const auto contentBoxSize = aReflowInput.ComputedSizeWithBSizeFallback([&] {
nscoord em = OneEmInAppUnits();
return ResolvedOrientationIsVertical() == wm.IsVertical() ? em : 10 * em;
});
aDesiredSize.SetSize(
wm,
contentBoxSize + aReflowInput.ComputedLogicalBorderPadding(wm).Size(wm));
aDesiredSize.SetOverflowAreasToDesiredBounds();
for (auto childFrame : PrincipalChildList()) {
ReflowChildFrame(childFrame, aPresContext, aReflowInput, aStatus);
for (nsIFrame* childFrame : PrincipalChildList()) {
ReflowChildFrame(childFrame, aPresContext, aReflowInput, contentBoxSize,
aStatus);
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, childFrame);
}
@ -115,14 +122,19 @@ void nsProgressFrame::Reflow(nsPresContext* aPresContext,
void nsProgressFrame::ReflowChildFrame(nsIFrame* aChild,
nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
const LogicalSize& aParentContentBoxSize,
nsReflowStatus& aStatus) {
bool vertical = ResolvedOrientationIsVertical();
WritingMode wm = aChild->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSize(wm);
const WritingMode wm = aChild->GetWritingMode();
const LogicalSize parentSizeInChildWM =
aParentContentBoxSize.ConvertTo(wm, aReflowInput.GetWritingMode());
const nsSize parentPhysicalSize = parentSizeInChildWM.GetPhysicalSize(wm);
LogicalSize availSize = parentSizeInChildWM;
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput reflowInput(aPresContext, aReflowInput, aChild, availSize);
ReflowInput reflowInput(aPresContext, aReflowInput, aChild, availSize,
Some(parentSizeInChildWM));
nscoord size =
vertical ? aReflowInput.ComputedHeight() : aReflowInput.ComputedWidth();
vertical ? parentPhysicalSize.Height() : parentPhysicalSize.Width();
nscoord xoffset = aReflowInput.ComputedPhysicalBorderPadding().left;
nscoord yoffset = aReflowInput.ComputedPhysicalBorderPadding().top;
@ -135,7 +147,7 @@ void nsProgressFrame::ReflowChildFrame(nsIFrame* aChild,
}
if (!vertical && wm.IsPhysicalRTL()) {
xoffset += aReflowInput.ComputedWidth() - size;
xoffset += parentPhysicalSize.Width() - size;
}
// The bar size is fixed in these cases:
@ -148,8 +160,7 @@ void nsProgressFrame::ReflowChildFrame(nsIFrame* aChild,
if (position != -1 || ShouldUseNativeStyle()) {
if (vertical) {
// We want the bar to begin at the bottom.
yoffset += aReflowInput.ComputedHeight() - size;
yoffset += parentPhysicalSize.Height() - size;
size -= reflowInput.ComputedPhysicalMargin().TopBottom() +
reflowInput.ComputedPhysicalBorderPadding().TopBottom();
size = std::max(size, 0);
@ -161,10 +172,12 @@ void nsProgressFrame::ReflowChildFrame(nsIFrame* aChild,
reflowInput.SetComputedWidth(size);
}
} else if (vertical) {
// For vertical progress bars, we need to position the bar specificly when
// For vertical progress bars, we need to position the bar specifically when
// the width isn't constrained (position == -1 and !ShouldUseNativeStyle())
// because aReflowInput.ComputedHeight() - size == 0.
yoffset += aReflowInput.ComputedHeight() - reflowInput.ComputedHeight();
// because parentPhysiscalSize.Height() - size == 0.
// FIXME(emilio): This assumes that the bar's height is constrained, which
// seems like a wrong assumption?
yoffset += parentPhysicalSize.Height() - reflowInput.ComputedHeight();
}
xoffset += reflowInput.ComputedPhysicalMargin().left;
@ -195,38 +208,11 @@ nsresult nsProgressFrame::AttributeChanged(int32_t aNameSpaceID,
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
}
LogicalSize nsProgressFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);
autoSize.BSize(wm) = autoSize.ISize(wm) =
StyleFont()
->mFont.size.ScaledBy(nsLayoutUtils::FontSizeInflationFor(this))
.ToAppUnits(); // 1em
if (ResolvedOrientationIsVertical() == wm.IsVertical()) {
autoSize.ISize(wm) *= 10; // 10em
} else {
autoSize.BSize(wm) *= 10; // 10em
}
return autoSize.ConvertTo(aWM, wm);
}
nscoord nsProgressFrame::GetMinISize(gfxContext* aRenderingContext) {
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, 1.0f);
nscoord minISize = fontMet->Font().size.ToAppUnits(); // 1em
nscoord minISize = OneEmInAppUnits();
if (ResolvedOrientationIsVertical() == GetWritingMode().IsVertical()) {
// The orientation is inline
minISize *= 10; // 10em
minISize *= 10;
}
return minISize;
}

View File

@ -18,8 +18,7 @@ enum class PseudoStyleType : uint8_t;
class nsProgressFrame final : public nsContainerFrame,
public nsIAnonymousContentCreator {
typedef mozilla::PseudoStyleType PseudoStyleType;
typedef mozilla::dom::Element Element;
using Element = mozilla::dom::Element;
public:
NS_DECL_QUERYFRAME
@ -30,38 +29,28 @@ class nsProgressFrame final : public nsContainerFrame,
void Destroy(DestroyContext&) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
virtual void Reflow(nsPresContext* aCX, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void Reflow(nsPresContext*, ReflowOutput&, const ReflowInput&,
nsReflowStatus&) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(u"Progress"_ns, aResult);
}
#endif
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(
nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
virtual mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
nscoord GetMinISize(gfxContext* aRenderingContext) override;
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
/**
* Returns whether the frame and its child should use the native style.
@ -72,6 +61,7 @@ class nsProgressFrame final : public nsContainerFrame,
// Helper function to reflow a child frame.
void ReflowChildFrame(nsIFrame* aChild, nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
const mozilla::LogicalSize& aParentContentBoxSize,
nsReflowStatus& aStatus);
/**

View File

@ -166,35 +166,17 @@ void nsRangeFrame::Reflow(nsPresContext* aPresContext,
"need to call RegUnregAccessKey only for the first.");
WritingMode wm = aReflowInput.GetWritingMode();
nscoord computedBSize = aReflowInput.ComputedBSize();
if (computedBSize == NS_UNCONSTRAINEDSIZE) {
computedBSize = 0;
}
const auto borderPadding = aReflowInput.ComputedLogicalBorderPadding(wm);
LogicalSize finalSize(
wm, aReflowInput.ComputedISize() + borderPadding.IStartEnd(wm),
computedBSize + borderPadding.BStartEnd(wm));
aDesiredSize.SetSize(wm, finalSize);
ReflowAnonymousContent(aPresContext, aDesiredSize, aReflowInput);
const auto contentBoxSize = aReflowInput.ComputedSizeWithBSizeFallback([&] {
return IsInlineOriented() ? AutoCrossSize()
: OneEmInAppUnits() * MAIN_AXIS_EM_SIZE;
});
aDesiredSize.SetSize(
wm,
contentBoxSize + aReflowInput.ComputedLogicalBorderPadding(wm).Size(wm));
aDesiredSize.SetOverflowAreasToDesiredBounds();
nsIFrame* trackFrame = mTrackDiv->GetPrimaryFrame();
if (trackFrame) {
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, trackFrame);
}
nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
if (rangeProgressFrame) {
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, rangeProgressFrame);
}
nsIFrame* thumbFrame = mThumbDiv->GetPrimaryFrame();
if (thumbFrame) {
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, thumbFrame);
}
ReflowAnonymousContent(aPresContext, aDesiredSize, contentBoxSize,
aReflowInput);
FinishAndStoreOverflow(&aDesiredSize);
MOZ_ASSERT(aStatus.IsEmpty(), "This type of frame can't be split.");
@ -202,111 +184,71 @@ void nsRangeFrame::Reflow(nsPresContext* aPresContext,
void nsRangeFrame::ReflowAnonymousContent(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const LogicalSize& aContentBoxSize,
const ReflowInput& aReflowInput) {
const auto parentWM = aReflowInput.GetWritingMode();
// The width/height of our content box, which is the available width/height
// for our anonymous content:
nscoord rangeFrameContentBoxWidth = aReflowInput.ComputedWidth();
nscoord rangeFrameContentBoxHeight = aReflowInput.ComputedHeight();
if (rangeFrameContentBoxHeight == NS_UNCONSTRAINEDSIZE) {
rangeFrameContentBoxHeight = 0;
}
nsIFrame* trackFrame = mTrackDiv->GetPrimaryFrame();
if (trackFrame) { // display:none?
// Position the track:
// The idea here is that we allow content authors to style the width,
// height, border and padding of the track, but we ignore margin and
// positioning properties and do the positioning ourself to keep the center
// of the track's border box on the center of the nsRangeFrame's content
// box.
WritingMode wm = trackFrame->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSize(wm);
// for our anonymous content.
const nsSize rangeFrameContentBoxSize =
aContentBoxSize.GetPhysicalSize(parentWM);
for (auto* div : {mTrackDiv.get(), mThumbDiv.get(), mProgressDiv.get()}) {
nsIFrame* child = div->GetPrimaryFrame();
if (!child) {
continue;
}
const WritingMode wm = child->GetWritingMode();
const LogicalSize parentSizeInChildWM =
aContentBoxSize.ConvertTo(wm, parentWM);
LogicalSize availSize = parentSizeInChildWM;
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput trackReflowInput(aPresContext, aReflowInput, trackFrame,
availSize);
ReflowInput childReflowInput(aPresContext, aReflowInput, child, availSize,
Some(parentSizeInChildWM));
// Find the x/y position of the track frame such that it will be positioned
// as described above. These coordinates are with respect to the
// nsRangeFrame's border-box.
nscoord trackX = rangeFrameContentBoxWidth / 2;
nscoord trackY = rangeFrameContentBoxHeight / 2;
const nsPoint pos = [&] {
if (div != mTrackDiv) {
// Where we position the thumb and range-progress depends on its size,
// so we first reflow them at {0,0} to obtain the size, then position
// them afterwards.
return nsPoint();
}
// Find the x/y position of the track. The idea here is that we allow
// content authors to style the width, height, border and padding of the
// track, but we ignore margin and positioning properties and do the
// positioning ourself to keep the center of the track's border box on the
// center of the nsRangeFrame's content. These coordinates are with
// respect to the nsRangeFrame's border-box.
nscoord trackX = rangeFrameContentBoxSize.Width() / 2;
nscoord trackY = rangeFrameContentBoxSize.Height() / 2;
// Account for the track's border and padding (we ignore its margin):
trackX -= trackReflowInput.ComputedPhysicalBorderPadding().left +
trackReflowInput.ComputedWidth() / 2;
trackY -= trackReflowInput.ComputedPhysicalBorderPadding().top +
trackReflowInput.ComputedHeight() / 2;
// Account for the track's border and padding (we ignore its margin):
// FIXME(emilio): Assumes the track height is constrained, which might not
// be true if authors override it.
trackX -= childReflowInput.ComputedPhysicalBorderPadding().left +
childReflowInput.ComputedWidth() / 2;
trackY -= childReflowInput.ComputedPhysicalBorderPadding().top +
childReflowInput.ComputedHeight() / 2;
// Make relative to our border box instead of our content box:
trackX += aReflowInput.ComputedPhysicalBorderPadding().left;
trackY += aReflowInput.ComputedPhysicalBorderPadding().top;
// Make relative to our border box instead of our content box:
trackX += aReflowInput.ComputedPhysicalBorderPadding().left;
trackY += aReflowInput.ComputedPhysicalBorderPadding().top;
return nsPoint(trackX, trackY);
}();
nsReflowStatus frameStatus;
ReflowOutput trackDesiredSize(aReflowInput);
ReflowChild(trackFrame, aPresContext, trackDesiredSize, trackReflowInput,
trackX, trackY, ReflowChildFlags::Default, frameStatus);
ReflowOutput childDesiredSize(aReflowInput);
ReflowChild(child, aPresContext, childDesiredSize, childReflowInput, pos.x,
pos.y, ReflowChildFlags::Default, frameStatus);
MOZ_ASSERT(
frameStatus.IsFullyComplete(),
"We gave our child unconstrained height, so it should be complete");
FinishReflowChild(trackFrame, aPresContext, trackDesiredSize,
&trackReflowInput, trackX, trackY,
ReflowChildFlags::Default);
}
nsIFrame* thumbFrame = mThumbDiv->GetPrimaryFrame();
if (thumbFrame) { // display:none?
WritingMode wm = thumbFrame->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSize(wm);
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput thumbReflowInput(aPresContext, aReflowInput, thumbFrame,
availSize);
// Where we position the thumb depends on its size, so we first reflow
// the thumb at {0,0} to obtain its size, then position it afterwards.
nsReflowStatus frameStatus;
ReflowOutput thumbDesiredSize(aReflowInput);
ReflowChild(thumbFrame, aPresContext, thumbDesiredSize, thumbReflowInput, 0,
0, ReflowChildFlags::Default, frameStatus);
MOZ_ASSERT(
frameStatus.IsFullyComplete(),
"We gave our child unconstrained height, so it should be complete");
FinishReflowChild(thumbFrame, aPresContext, thumbDesiredSize,
&thumbReflowInput, 0, 0, ReflowChildFlags::Default);
DoUpdateThumbPosition(thumbFrame,
nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
}
nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
if (rangeProgressFrame) { // display:none?
WritingMode wm = rangeProgressFrame->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSize(wm);
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
ReflowInput progressReflowInput(aPresContext, aReflowInput,
rangeProgressFrame, availSize);
// We first reflow the range-progress frame at {0,0} to obtain its
// unadjusted dimensions, then we adjust it to so that the appropriate edge
// ends at the thumb.
nsReflowStatus frameStatus;
ReflowOutput progressDesiredSize(aReflowInput);
ReflowChild(rangeProgressFrame, aPresContext, progressDesiredSize,
progressReflowInput, 0, 0, ReflowChildFlags::Default,
frameStatus);
MOZ_ASSERT(
frameStatus.IsFullyComplete(),
"We gave our child unconstrained height, so it should be complete");
FinishReflowChild(rangeProgressFrame, aPresContext, progressDesiredSize,
&progressReflowInput, 0, 0, ReflowChildFlags::Default);
DoUpdateRangeProgressFrame(
rangeProgressFrame,
nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
FinishReflowChild(child, aPresContext, childDesiredSize, &childReflowInput,
pos.x, pos.y, ReflowChildFlags::Default);
if (div == mThumbDiv) {
DoUpdateThumbPosition(child, rangeFrameContentBoxSize);
} else if (div == mProgressDiv) {
DoUpdateRangeProgressFrame(child, rangeFrameContentBoxSize);
}
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, child);
}
}
@ -539,7 +481,7 @@ mozilla::dom::HTMLInputElement& nsRangeFrame::InputElement() const {
}
void nsRangeFrame::DoUpdateThumbPosition(nsIFrame* aThumbFrame,
const nsSize& aRangeSize) {
const nsSize& aRangeContentBoxSize) {
MOZ_ASSERT(aThumbFrame);
// The idea here is that we want to position the thumb so that the center
@ -553,29 +495,26 @@ void nsRangeFrame::DoUpdateThumbPosition(nsIFrame* aThumbFrame,
nsMargin borderAndPadding = GetUsedBorderAndPadding();
nsPoint newPosition(borderAndPadding.left, borderAndPadding.top);
nsSize rangeContentBoxSize(aRangeSize);
rangeContentBoxSize.width -= borderAndPadding.LeftRight();
rangeContentBoxSize.height -= borderAndPadding.TopBottom();
nsSize thumbSize = aThumbFrame->GetSize();
double fraction = GetValueAsFractionOfRange();
MOZ_ASSERT(fraction >= 0.0 && fraction <= 1.0);
if (IsHorizontal()) {
if (thumbSize.width < rangeContentBoxSize.width) {
nscoord traversableDistance = rangeContentBoxSize.width - thumbSize.width;
if (thumbSize.width < aRangeContentBoxSize.width) {
nscoord traversableDistance =
aRangeContentBoxSize.width - thumbSize.width;
if (IsRightToLeft()) {
newPosition.x += NSToCoordRound((1.0 - fraction) * traversableDistance);
} else {
newPosition.x += NSToCoordRound(fraction * traversableDistance);
}
newPosition.y += (rangeContentBoxSize.height - thumbSize.height) / 2;
newPosition.y += (aRangeContentBoxSize.height - thumbSize.height) / 2;
}
} else {
if (thumbSize.height < rangeContentBoxSize.height) {
if (thumbSize.height < aRangeContentBoxSize.height) {
nscoord traversableDistance =
rangeContentBoxSize.height - thumbSize.height;
newPosition.x += (rangeContentBoxSize.width - thumbSize.width) / 2;
aRangeContentBoxSize.height - thumbSize.height;
newPosition.x += (aRangeContentBoxSize.width - thumbSize.width) / 2;
if (IsUpwards()) {
newPosition.y += NSToCoordRound((1.0 - fraction) * traversableDistance);
} else {
@ -586,9 +525,9 @@ void nsRangeFrame::DoUpdateThumbPosition(nsIFrame* aThumbFrame,
aThumbFrame->SetPosition(newPosition);
}
void nsRangeFrame::DoUpdateRangeProgressFrame(nsIFrame* aRangeProgressFrame,
const nsSize& aRangeSize) {
MOZ_ASSERT(aRangeProgressFrame);
void nsRangeFrame::DoUpdateRangeProgressFrame(
nsIFrame* aProgressFrame, const nsSize& aRangeContentBoxSize) {
MOZ_ASSERT(aProgressFrame);
// The idea here is that we want to position the ::-moz-range-progress
// pseudo-element so that the center line running along its length is on the
@ -598,35 +537,30 @@ void nsRangeFrame::DoUpdateRangeProgressFrame(nsIFrame* aRangeProgressFrame,
// nsRangeFrame's content box, and we size the progress element's border-box
// to have a length of GetValueAsFractionOfRange() times the nsRangeFrame's
// content-box size.
nsMargin borderAndPadding = GetUsedBorderAndPadding();
nsSize progSize = aRangeProgressFrame->GetSize();
nsSize progSize = aProgressFrame->GetSize();
nsRect progRect(borderAndPadding.left, borderAndPadding.top, progSize.width,
progSize.height);
nsSize rangeContentBoxSize(aRangeSize);
rangeContentBoxSize.width -= borderAndPadding.LeftRight();
rangeContentBoxSize.height -= borderAndPadding.TopBottom();
double fraction = GetValueAsFractionOfRange();
MOZ_ASSERT(fraction >= 0.0 && fraction <= 1.0);
if (IsHorizontal()) {
nscoord progLength = NSToCoordRound(fraction * rangeContentBoxSize.width);
nscoord progLength = NSToCoordRound(fraction * aRangeContentBoxSize.width);
if (IsRightToLeft()) {
progRect.x += rangeContentBoxSize.width - progLength;
progRect.x += aRangeContentBoxSize.width - progLength;
}
progRect.y += (rangeContentBoxSize.height - progSize.height) / 2;
progRect.y += (aRangeContentBoxSize.height - progSize.height) / 2;
progRect.width = progLength;
} else {
nscoord progLength = NSToCoordRound(fraction * rangeContentBoxSize.height);
progRect.x += (rangeContentBoxSize.width - progSize.width) / 2;
nscoord progLength = NSToCoordRound(fraction * aRangeContentBoxSize.height);
progRect.x += (aRangeContentBoxSize.width - progSize.width) / 2;
if (IsUpwards()) {
progRect.y += rangeContentBoxSize.height - progLength;
progRect.y += aRangeContentBoxSize.height - progLength;
}
progRect.height = progLength;
}
aRangeProgressFrame->SetRect(progRect);
aProgressFrame->SetRect(progRect);
}
nsresult nsRangeFrame::AttributeChanged(int32_t aNameSpaceID,
@ -677,7 +611,7 @@ nsresult nsRangeFrame::AttributeChanged(int32_t aNameSpaceID,
return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
}
nscoord nsRangeFrame::AutoCrossSize(Length aEm) {
nscoord nsRangeFrame::AutoCrossSize() {
nscoord minCrossSize(0);
if (IsThemed()) {
nsPresContext* pc = PresContext();
@ -686,33 +620,8 @@ nscoord nsRangeFrame::AutoCrossSize(Length aEm) {
minCrossSize =
pc->DevPixelsToAppUnits(IsHorizontal() ? size.height : size.width);
}
return std::max(minCrossSize, aEm.ScaledBy(CROSS_AXIS_EM_SIZE).ToAppUnits());
}
static mozilla::Length OneEm(nsRangeFrame* aFrame) {
return aFrame->StyleFont()->mFont.size.ScaledBy(
nsLayoutUtils::FontSizeInflationFor(aFrame));
}
LogicalSize nsRangeFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
bool isInlineOriented = IsInlineOriented();
auto em = OneEm(this);
const WritingMode wm = GetWritingMode();
LogicalSize autoSize(wm);
if (isInlineOriented) {
autoSize.ISize(wm) = em.ScaledBy(MAIN_AXIS_EM_SIZE).ToAppUnits();
autoSize.BSize(wm) = AutoCrossSize(em);
} else {
autoSize.ISize(wm) = AutoCrossSize(em);
autoSize.BSize(wm) = em.ScaledBy(MAIN_AXIS_EM_SIZE).ToAppUnits();
}
return autoSize.ConvertTo(aWM, wm);
return std::max(minCrossSize,
NSToCoordRound(OneEmInAppUnits() * CROSS_AXIS_EM_SIZE));
}
nscoord nsRangeFrame::GetMinISize(gfxContext* aRenderingContext) {
@ -728,11 +637,10 @@ nscoord nsRangeFrame::GetMinISize(gfxContext* aRenderingContext) {
}
nscoord nsRangeFrame::GetPrefISize(gfxContext* aRenderingContext) {
auto em = OneEm(this);
if (IsInlineOriented()) {
return em.ScaledBy(MAIN_AXIS_EM_SIZE).ToAppUnits();
return OneEmInAppUnits() * MAIN_AXIS_EM_SIZE;
}
return AutoCrossSize(em);
return AutoCrossSize();
}
bool nsRangeFrame::IsHorizontal() const {

View File

@ -7,12 +7,10 @@
#ifndef nsRangeFrame_h___
#define nsRangeFrame_h___
#include "mozilla/Attributes.h"
#include "mozilla/Decimal.h"
#include "mozilla/EventForwards.h"
#include "nsContainerFrame.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIDOMEventListener.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
@ -40,8 +38,7 @@ class nsRangeFrame final : public nsContainerFrame,
explicit nsRangeFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
virtual ~nsRangeFrame();
typedef mozilla::PseudoStyleType PseudoStyleType;
typedef mozilla::dom::Element Element;
using Element = mozilla::dom::Element;
public:
NS_DECL_QUERYFRAME
@ -53,39 +50,30 @@ class nsRangeFrame final : public nsContainerFrame,
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(u"Range"_ns, aResult);
}
#endif
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
mozilla::a11y::AccType AccessibleType() override;
#endif
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(
nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType) override;
mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
nscoord GetMinISize(gfxContext* aRenderingContext) override;
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
/**
* Returns true if the slider's thumb moves horizontally, or else false if it
@ -171,17 +159,19 @@ class nsRangeFrame final : public nsContainerFrame,
private:
// Return our preferred size in the cross-axis (the axis perpendicular
// to the direction of movement of the thumb).
nscoord AutoCrossSize(mozilla::Length aEm);
nscoord AutoCrossSize();
// Helper function which reflows the anonymous div frames.
void ReflowAnonymousContent(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const mozilla::LogicalSize& aContentBoxSize,
const ReflowInput& aReflowInput);
void DoUpdateThumbPosition(nsIFrame* aThumbFrame, const nsSize& aRangeSize);
void DoUpdateThumbPosition(nsIFrame* aThumbFrame,
const nsSize& aRangeContentBoxSize);
void DoUpdateRangeProgressFrame(nsIFrame* aProgressFrame,
const nsSize& aRangeSize);
const nsSize& aRangeContentBoxSize);
/**
* The div used to show the ::-moz-range-track pseudo-element.

View File

@ -173,15 +173,14 @@ void nsTextControlFrame::Destroy(DestroyContext& aContext) {
nsContainerFrame::Destroy(aContext);
}
LogicalSize nsTextControlFrame::CalcIntrinsicSize(
gfxContext* aRenderingContext, WritingMode aWM,
float aFontSizeInflation) const {
LogicalSize nsTextControlFrame::CalcIntrinsicSize(gfxContext* aRenderingContext,
WritingMode aWM) const {
LogicalSize intrinsicSize(aWM);
const float inflation = nsLayoutUtils::FontSizeInflationFor(this);
RefPtr<nsFontMetrics> fontMet =
nsLayoutUtils::GetFontMetricsForFrame(this, aFontSizeInflation);
const nscoord lineHeight =
ReflowInput::CalcLineHeight(*Style(), PresContext(), GetContent(),
NS_UNCONSTRAINEDSIZE, aFontSizeInflation);
nsLayoutUtils::GetFontMetricsForFrame(this, inflation);
const nscoord lineHeight = ReflowInput::CalcLineHeight(
*Style(), PresContext(), GetContent(), NS_UNCONSTRAINEDSIZE, inflation);
// Use the larger of the font's "average" char width or the width of the
// zero glyph (if present) as the basis for resolving the size attribute.
const nscoord charWidth =
@ -556,9 +555,8 @@ void nsTextControlFrame::AppendAnonymousContentTo(
nscoord nsTextControlFrame::GetPrefISize(gfxContext* aRenderingContext) {
nscoord result = 0;
DISPLAY_PREF_INLINE_SIZE(this, result);
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
WritingMode wm = GetWritingMode();
result = CalcIntrinsicSize(aRenderingContext, wm, inflation).ISize(wm);
result = CalcIntrinsicSize(aRenderingContext, wm).ISize(wm);
return result;
}
@ -570,44 +568,6 @@ nscoord nsTextControlFrame::GetMinISize(gfxContext* aRenderingContext) {
return result;
}
LogicalSize nsTextControlFrame::ComputeAutoSize(
gfxContext* aRenderingContext, WritingMode aWM, const LogicalSize& aCBSize,
nscoord aAvailableISize, const LogicalSize& aMargin,
const LogicalSize& aBorderPadding, const StyleSizeOverrides& aSizeOverrides,
ComputeSizeFlags aFlags) {
float inflation = nsLayoutUtils::FontSizeInflationFor(this);
LogicalSize autoSize = CalcIntrinsicSize(aRenderingContext, aWM, inflation);
// Note: nsContainerFrame::ComputeAutoSize only computes the inline-size (and
// only for 'auto'), the block-size it returns is always NS_UNCONSTRAINEDSIZE.
const auto& styleISize = aSizeOverrides.mStyleISize
? *aSizeOverrides.mStyleISize
: StylePosition()->ISize(aWM);
if (styleISize.IsAuto()) {
if (aFlags.contains(ComputeSizeFlag::IClampMarginBoxMinSize)) {
// CalcIntrinsicSize isn't aware of grid-item margin-box clamping, so we
// fall back to nsContainerFrame's ComputeAutoSize to handle that.
// XXX maybe a font-inflation issue here? (per the assertion below).
autoSize.ISize(aWM) =
nsContainerFrame::ComputeAutoSize(
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin,
aBorderPadding, aSizeOverrides, aFlags)
.ISize(aWM);
}
#ifdef DEBUG
else {
LogicalSize ancestorAutoSize = nsContainerFrame::ComputeAutoSize(
aRenderingContext, aWM, aCBSize, aAvailableISize, aMargin,
aBorderPadding, aSizeOverrides, aFlags);
MOZ_ASSERT(inflation != 1.0f ||
ancestorAutoSize.ISize(aWM) == autoSize.ISize(aWM),
"Incorrect size computed by ComputeAutoSize?");
}
#endif
}
return autoSize;
}
Maybe<nscoord> nsTextControlFrame::ComputeBaseline(
const nsIFrame* aFrame, const ReflowInput& aReflowInput,
bool aForSingleLineControl) {
@ -646,7 +606,12 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
// set values of reflow's out parameters
WritingMode wm = aReflowInput.GetWritingMode();
aDesiredSize.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding(wm));
const auto contentBoxSize = aReflowInput.ComputedSizeWithBSizeFallback([&] {
return CalcIntrinsicSize(aReflowInput.mRenderingContext, wm).BSize(wm);
});
aDesiredSize.SetSize(
wm,
contentBoxSize + aReflowInput.ComputedLogicalBorderPadding(wm).Size(wm));
{
// Calculate the baseline and store it in mFirstBaseline.
@ -674,7 +639,7 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
nscoord buttonBoxISize = 0;
if (buttonBox) {
ReflowTextControlChild(buttonBox, aPresContext, aReflowInput, aStatus,
aDesiredSize, buttonBoxISize);
aDesiredSize, contentBoxSize, buttonBoxISize);
}
// perform reflow on all kids
@ -684,7 +649,7 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
MOZ_ASSERT(!IsButtonBox(kid),
"Should only have one button box, and should be last");
ReflowTextControlChild(kid, aPresContext, aReflowInput, aStatus,
aDesiredSize, buttonBoxISize);
aDesiredSize, contentBoxSize, buttonBoxISize);
}
kid = kid->GetNextSibling();
}
@ -698,22 +663,28 @@ void nsTextControlFrame::Reflow(nsPresContext* aPresContext,
void nsTextControlFrame::ReflowTextControlChild(
nsIFrame* aKid, nsPresContext* aPresContext,
const ReflowInput& aReflowInput, nsReflowStatus& aStatus,
ReflowOutput& aParentDesiredSize, nscoord& aButtonBoxISize) {
ReflowOutput& aParentDesiredSize, const LogicalSize& aParentContentBoxSize,
nscoord& aButtonBoxISize) {
const WritingMode outerWM = aReflowInput.GetWritingMode();
// compute available size and frame offsets for child
const WritingMode wm = aKid->GetWritingMode();
LogicalSize availSize = aReflowInput.ComputedSizeWithPadding(wm);
const auto parentPadding = aReflowInput.ComputedLogicalPadding(wm);
const LogicalSize contentBoxSize =
aParentContentBoxSize.ConvertTo(wm, outerWM);
const LogicalSize paddingBoxSize = contentBoxSize + parentPadding.Size(wm);
const LogicalSize borderBoxSize =
paddingBoxSize + aReflowInput.ComputedLogicalBorder(wm).Size(wm);
LogicalSize availSize = paddingBoxSize;
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
bool isButtonBox = IsButtonBox(aKid);
const bool isButtonBox = IsButtonBox(aKid);
ReflowInput kidReflowInput(aPresContext, aReflowInput, aKid, availSize,
Nothing(), ReflowInput::InitFlag::CallerWillInit);
// Override padding with our computed padding in case we got it from theming
// or percentage, if we're not the button box.
auto overridePadding =
isButtonBox ? Nothing() : Some(aReflowInput.ComputedLogicalPadding(wm));
auto overridePadding = isButtonBox ? Nothing() : Some(parentPadding);
if (!isButtonBox && aButtonBoxISize) {
// Button box respects inline-end-padding, so we don't need to.
overridePadding->IEnd(outerWM) = 0;
@ -722,8 +693,7 @@ void nsTextControlFrame::ReflowTextControlChild(
// We want to let our button box fill the frame in the block axis, up to the
// edge of the control's border. So, we use the control's padding-box as the
// containing block size for our button box.
auto overrideCBSize =
isButtonBox ? Some(aReflowInput.ComputedSizeWithPadding(wm)) : Nothing();
auto overrideCBSize = isButtonBox ? Some(paddingBoxSize) : Nothing();
kidReflowInput.Init(aPresContext, overrideCBSize, Nothing(), overridePadding);
LogicalPoint position(wm);
@ -746,14 +716,12 @@ void nsTextControlFrame::ReflowTextControlChild(
// the only exception, which has an auto size).
kidReflowInput.SetComputedISize(
std::max(0, aReflowInput.ComputedISize() - aButtonBoxISize));
kidReflowInput.SetComputedBSize(aReflowInput.ComputedBSize());
kidReflowInput.SetComputedBSize(contentBoxSize.BSize(wm));
}
// reflow the child
ReflowOutput desiredSize(aReflowInput);
const nsSize containerSize =
aReflowInput.ComputedSizeWithBorderPadding(outerWM).GetPhysicalSize(
outerWM);
const nsSize containerSize = borderBoxSize.GetPhysicalSize(wm);
ReflowChild(aKid, aPresContext, desiredSize, kidReflowInput, wm, position,
containerSize, ReflowChildFlags::Default, aStatus);
@ -767,7 +735,7 @@ void nsTextControlFrame::ReflowTextControlChild(
buttonRect.ISize(outerWM) = size.ISize(outerWM);
buttonRect.BStart(outerWM) =
bp.BStart(outerWM) +
(aReflowInput.ComputedBSize() - size.BSize(outerWM)) / 2;
(aParentContentBoxSize.BSize(outerWM) - size.BSize(outerWM)) / 2;
// Align to the inline-end of the content box.
buttonRect.IStart(outerWM) =
bp.IStart(outerWM) + aReflowInput.ComputedISize() - size.ISize(outerWM);

View File

@ -63,14 +63,6 @@ class nsTextControlFrame : public nsContainerFrame,
nscoord GetMinISize(gfxContext* aRenderingContext) override;
nscoord GetPrefISize(gfxContext* aRenderingContext) override;
mozilla::LogicalSize ComputeAutoSize(
gfxContext* aRenderingContext, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
const mozilla::LogicalSize& aMargin,
const mozilla::LogicalSize& aBorderPadding,
const mozilla::StyleSizeOverrides& aSizeOverrides,
mozilla::ComputeSizeFlags aFlags) override;
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
@ -180,10 +172,11 @@ class nsTextControlFrame : public nsContainerFrame,
/**
* Launch the reflow on the child frames - see nsTextControlFrame::Reflow()
*/
void ReflowTextControlChild(nsIFrame* aFrame, nsPresContext* aPresContext,
void ReflowTextControlChild(nsIFrame* aKid, nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus,
ReflowOutput& aParentDesiredSize,
const mozilla::LogicalSize& aParentContentBoxSize,
nscoord& aButtonBoxISize);
public:
@ -278,8 +271,7 @@ class nsTextControlFrame : public nsContainerFrame,
// etc. Just the size of our actual area for the text (and the scrollbars,
// for <textarea>).
mozilla::LogicalSize CalcIntrinsicSize(gfxContext* aRenderingContext,
mozilla::WritingMode aWM,
float aFontSizeInflation) const;
mozilla::WritingMode aWM) const;
private:
// helper methods

View File

@ -13,10 +13,8 @@
#include "CounterStyleManager.h"
#include "LayoutLogging.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/WritingModes.h"
#include "nsBlockFrame.h"
#include "nsCSSAnonBoxes.h"
#include "nsFlexContainerFrame.h"
#include "nsFontInflationData.h"
#include "nsFontMetrics.h"
@ -31,7 +29,6 @@
#include "nsLineBox.h"
#include "nsPresContext.h"
#include "nsStyleConsts.h"
#include "nsTableCellFrame.h"
#include "nsTableFrame.h"
#include "StickyScrollContainer.h"
@ -1292,7 +1289,6 @@ void ReflowInput::CalculateHypotheticalPosition(
// For non-replaced inline-level elements the 'inline size' property
// doesn't apply, so we don't know what the inline size would have
// been without reflowing it
} else {
// It's either a replaced inline-level element or a block-level element
@ -1305,13 +1301,12 @@ void ReflowInput::CalculateHypotheticalPosition(
&insideBoxISizing, &outsideBoxISizing);
if (mFlags.mIsReplaced && isAutoISize) {
// It's a replaced element with an 'auto' inline size so the box
// inline size is its intrinsic size plus any border/padding/margin
// It's a replaced element with an 'auto' inline size so the box inline
// size is its intrinsic size plus any border/padding/margin
if (intrinsicSize) {
boxISize.emplace(LogicalSize(wm, *intrinsicSize).ISize(wm) +
outsideBoxISizing + insideBoxISizing);
}
} else if (isAutoISize) {
// The box inline size is the containing block inline size
boxISize.emplace(blockContentSize.ISize(wm));
@ -2239,7 +2234,7 @@ void ReflowInput::InitConstraints(
// eStyleUnit_Auto;" used to be called exclusively.
if (mFlags.mIsReplaced && mStyleDisplay->IsInlineOutsideStyle()) {
// Get the containing block's reflow input
NS_ASSERTION(nullptr != cbri, "no containing block");
NS_ASSERTION(cbri, "no containing block");
// in quirks mode, get the cb height using the special quirk method
if (!wm.IsVertical() &&
eCompatibility_NavQuirks == aPresContext->CompatibilityMode()) {
@ -2359,46 +2354,79 @@ void ReflowInput::InitConstraints(
} else {
AutoMaybeDisableFontInflation an(mFrame);
const bool isBlockLevel =
((!mStyleDisplay->IsInlineOutsideStyle() &&
// internal table values on replaced elements behaves as inline
// https://drafts.csswg.org/css-tables-3/#table-structure
// "... it is handled instead as though the author had declared
// either 'block' (for 'table' display) or 'inline' (for all
// other values)"
!(mFlags.mIsReplaced && (mStyleDisplay->IsInnerTableStyle() ||
mStyleDisplay->DisplayOutside() ==
StyleDisplayOutside::TableCaption))) ||
// The inner table frame always fills its outer wrapper table frame,
// even for 'inline-table'.
mFrame->IsTableFrame()) &&
// XXX abs.pos. continuations treated like blocks, see comment in
// the else-if condition above.
(!mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) ||
mStyleDisplay->IsAbsolutelyPositionedStyle());
nsIFrame* const alignCB = [&] {
nsIFrame* cb = mFrame->GetParent();
if (cb->IsTableWrapperFrame()) {
nsIFrame* alignCBParent = cb->GetParent();
if (alignCBParent && alignCBParent->IsGridContainerFrame()) {
return alignCBParent;
}
}
return cb;
}();
if (!isBlockLevel) {
const bool isInlineLevel = [&] {
if (mFrame->IsTableFrame()) {
// An inner table frame is not inline-level, even if it happens to
// have 'display:inline-table'. (That makes its table-wrapper frame be
// inline-level, but not the inner table frame)
return false;
}
if (mStyleDisplay->IsInlineOutsideStyle()) {
return true;
}
if (mFlags.mIsReplaced && (mStyleDisplay->IsInnerTableStyle() ||
mStyleDisplay->DisplayOutside() ==
StyleDisplayOutside::TableCaption)) {
// Internal table values on replaced elements behave as inline
// https://drafts.csswg.org/css-tables-3/#table-structure
//
// ... it is handled instead as though the author had declared
// either 'block' (for 'table' display) or 'inline' (for all
// other values)"
//
// FIXME(emilio): The only test that covers this is
// table-anonymous-objects-211.xht, which fails on other browsers (but
// differently to us, if you just remove this condition).
return true;
}
if (mFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
!mStyleDisplay->IsAbsolutelyPositionedStyle()) {
// Floats are treated as inline-level and also shrink-wrap.
return true;
}
return false;
}();
const bool shouldShrinkWrap = [&] {
if (isInlineLevel) {
return true;
}
if (mFlags.mIsReplaced && !alignCB->IsFlexOrGridContainer()) {
// Shrink-wrap replaced elements when in-flow (out of flows are
// handled above). We exclude replaced elements in grid or flex
// contexts, where we don't want to shrink-wrap unconditionally (so
// that stretching can happen). When grid/flex explicitly want
// shrink-wrapping, they can request it directly using the relevant
// flag.
return true;
}
if (!alignCB->IsGridContainerFrame() && mCBReflowInput &&
mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) {
// Shrink-wrap blocks that are orthogonal to their container (unless
// we're in a grid?)
return true;
}
return false;
}();
if (shouldShrinkWrap) {
mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap;
}
nsIFrame* alignCB = mFrame->GetParent();
if (alignCB->IsTableWrapperFrame()) {
nsIFrame* alignCBParent = alignCB->GetParent();
if (alignCBParent && alignCBParent->IsGridContainerFrame()) {
alignCB = alignCBParent;
}
}
if (!alignCB->IsGridContainerFrame()) {
// Shrink-wrap blocks that are orthogonal to their container.
if (isBlockLevel && mCBReflowInput &&
mCBReflowInput->GetWritingMode().IsOrthogonalTo(mWritingMode)) {
mComputeSizeFlags += ComputeSizeFlag::ShrinkWrap;
}
}
if (cbSize.ISize(wm) == NS_UNCONSTRAINEDSIZE) {
// For orthogonal flows, where we found a parent orthogonal-limit
// for AvailableISize() in Init(), we'll use the same here as well.
// For orthogonal flows, where we found a parent orthogonal-limit for
// AvailableISize() in Init(), we'll use the same here as well.
cbSize.ISize(wm) = AvailableISize();
}
@ -2418,10 +2446,7 @@ void ReflowInput::InitConstraints(
size.mAspectRatioUsage == nsIFrame::AspectRatioUsage::ToComputeBSize;
const bool shouldCalculateBlockSideMargins = [&]() {
if (!isBlockLevel) {
return false;
}
if (mStyleDisplay->mDisplay == StyleDisplay::InlineTable) {
if (isInlineLevel) {
return false;
}
if (mFrame->IsTableFrame()) {

View File

@ -367,6 +367,16 @@ struct ReflowInput : public SizeComputationInput {
mozilla::LogicalSize AvailableSize() const { return mAvailableSize; }
mozilla::LogicalSize ComputedSize() const { return mComputedSize; }
template <typename F>
mozilla::LogicalSize ComputedSizeWithBSizeFallback(F&& aFallback) const {
auto size = mComputedSize;
if (size.BSize(mWritingMode) == NS_UNCONSTRAINEDSIZE) {
size.BSize(mWritingMode) = ApplyMinMaxBSize(aFallback());
}
return size;
}
mozilla::LogicalSize ComputedMinSize() const { return mComputedMinSize; }
mozilla::LogicalSize ComputedMaxSize() const { return mComputedMaxSize; }

View File

@ -814,8 +814,7 @@ LogicalSize nsContainerFrame::ComputeAutoSize(
LogicalSize result(aWM, 0xdeadbeef, NS_UNCONSTRAINEDSIZE);
nscoord availBased =
aAvailableISize - aMargin.ISize(aWM) - aBorderPadding.ISize(aWM);
// replaced elements always shrink-wrap
if (aFlags.contains(ComputeSizeFlag::ShrinkWrap) || IsReplaced()) {
if (aFlags.contains(ComputeSizeFlag::ShrinkWrap)) {
// Only bother computing our 'auto' ISize if the result will be used.
const auto& styleISize = aSizeOverrides.mStyleISize
? *aSizeOverrides.mStyleISize

View File

@ -2017,6 +2017,12 @@ bool nsIFrame::GetShapeBoxBorderRadii(nscoord aRadii[8]) const {
}
}
nscoord nsIFrame::OneEmInAppUnits() const {
return StyleFont()
->mFont.size.ScaledBy(nsLayoutUtils::FontSizeInflationFor(this))
.ToAppUnits();
}
ComputedStyle* nsIFrame::GetAdditionalComputedStyle(int32_t aIndex) const {
MOZ_ASSERT(aIndex >= 0, "invalid index number");
return nullptr;

View File

@ -1585,6 +1585,11 @@ class nsIFrame : public nsQueryFrame {
bool GetBoxBorderRadii(nscoord aRadii[8], const nsMargin& aOffset) const;
bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const;
/**
* Returns one em unit, adjusted for font inflation if needed, in app units.
*/
nscoord OneEmInAppUnits() const;
/**
* `GetNaturalBaselineBOffset`, but determines the baseline sharing group
* through `GetDefaultBaselineSharingGroup` (If not specified), assuming line

View File

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<div style="position: absolute; width: 100px;">
<input style="position: absolute; top: 0; left: 0;">
</div>
</body>
</html>

View File

@ -1,8 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<div style="position: absolute; width: 100px;">
<input style="position: absolute; top: 0; left: 0; right: 0">
</div>
</body>
</html>

View File

@ -1,51 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#red {
position: absolute;
background-color: blue;
top: 10px;
left: 10px;
}
#green {
position: absolute;
background-color: blue;
top: 10px;
width: 80px;
right: 10px;
}
#blue {
position: absolute;
background-color: blue;
left: 10px;
height: 80px;
bottom: 10px;
}
#yellow {
position: absolute;
background-color: blue;
right: 10px;
width: 80px;
height: 80px;
bottom: 10px;
}
</style>
<script>
</script>
</head>
<body>
<textarea id=red></textarea>
<textarea id=green></textarea>
<textarea id=blue></textarea>
<textarea id=yellow></textarea>
</body>
</html>

View File

@ -1,55 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#red {
position: absolute;
background-color: blue;
top: 10px;
left: 10px;
right: 100px;
bottom: 100px;
}
#green {
position: absolute;
background-color: blue;
top: 10px;
width: 80px;
right: 10px;
bottom: 100px;
}
#blue {
position: absolute;
background-color: blue;
left: 10px;
height: 80px;
right: 100px;
bottom: 10px;
}
#yellow {
position: absolute;
background-color: blue;
right: 10px;
width: 80px;
height: 80px;
bottom: 10px;
}
</style>
<script>
</script>
</head>
<body>
<textarea id=red></textarea>
<textarea id=green></textarea>
<textarea id=blue></textarea>
<textarea id=yellow></textarea>
</body>
</html>

View File

@ -1,51 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#red {
position: absolute;
background-color: blue;
top: 10px;
left: 10px;
}
#green {
position: absolute;
background-color: blue;
top: 10px;
width: 80px;
right: 10px;
}
#blue {
position: absolute;
background-color: blue;
left: 10px;
height: 80px;
bottom: 10px;
}
#yellow {
position: absolute;
background-color: blue;
right: 10px;
width: 80px;
height: 80px;
bottom: 10px;
}
</style>
<script>
</script>
</head>
<body>
<input id=red>
<input id=green>
<input id=blue>
<input id=yellow>
</body>
</html>

View File

@ -1,55 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#red {
position: absolute;
background-color: blue;
top: 10px;
left: 10px;
right: 100px;
bottom: 100px;
}
#green {
position: absolute;
background-color: blue;
top: 10px;
width: 80px;
right: 10px;
bottom: 100px;
}
#blue {
position: absolute;
background-color: blue;
left: 10px;
height: 80px;
right: 100px;
bottom: 10px;
}
#yellow {
position: absolute;
background-color: blue;
right: 10px;
width: 80px;
height: 80px;
bottom: 10px;
}
</style>
<script>
</script>
</head>
<body>
<input id=red>
<input id=green>
<input id=blue>
<input id=yellow>
</body>
</html>

View File

@ -342,7 +342,6 @@ skip-if(useDrawSnapshot) == 306660-2.html 306660-2-ref.html
== 306660-3.html 306660-3-ref.html
== 307076-1.html 307076-1-ref.html
== 307102-1.html 307102-1-ref.html
== 307102-2.html 307102-2-ref.html
== 307102-3.html 307102-3-ref.html
== 307102-4.html 307102-4-ref.html
== 308406-1.html 308406-1-ref.html
@ -725,8 +724,6 @@ fuzzy(0-2,0-5) == 381507-1.html 381507-1-ref.html
fuzzy(0-1,0-600) == 385823-2a.html 385823-2-ref.html
fails == 385823-2b.html 385823-2-ref.html
fuzzy(0-1,0-600) == 385823-2c.html 385823-2-ref.html
fuzzy(0-2,0-11) == 385870-1.html 385870-1-ref.html
fuzzy(0-2,0-3) == 385870-2.html 385870-2-ref.html
== 386014-1a.html 386014-1-ref.html
== 386014-1b.html 386014-1-ref.html
== 386014-1c.html 386014-1-ref.html

View File

@ -1,2 +0,0 @@
[position-absolute-semi-replaced-stretch-button.html]
expected: FAIL

View File

@ -1,2 +0,0 @@
[position-absolute-semi-replaced-stretch-input.html]
expected: FAIL

View File

@ -1,2 +0,0 @@
[position-absolute-semi-replaced-stretch-other.html]
expected: FAIL