浏览代码

Rename BuildBoxModes, make caller specify that fit-content should be applied

Michael Ragazzon 5 月之前
父节点
当前提交
89fe7a2c8d

+ 2 - 2
Source/Core/ElementScroll.cpp

@@ -66,7 +66,7 @@ void ElementScroll::EnableScrollbar(Orientation orientation, float element_width
 
 
 	// Determine the size of the scrollbar.
 	// Determine the size of the scrollbar.
 	Box box;
 	Box box;
-	LayoutDetails::BuildBox(box, Vector2f(element_width, element_width), scrollbars[orientation].element, BuildBoxMode::UnalignedBlock);
+	LayoutDetails::BuildBox(box, Vector2f(element_width, element_width), scrollbars[orientation].element, BuildBoxMode::Unaligned);
 
 
 	if (orientation == VERTICAL)
 	if (orientation == VERTICAL)
 		scrollbars[orientation].size = box.GetSize(BoxArea::Margin).x;
 		scrollbars[orientation].size = box.GetSize(BoxArea::Margin).x;
@@ -191,7 +191,7 @@ void ElementScroll::FormatScrollbars()
 		CreateCorner();
 		CreateCorner();
 
 
 		Box corner_box;
 		Box corner_box;
-		LayoutDetails::BuildBox(corner_box, Vector2f(containing_block.x), corner, BuildBoxMode::UnalignedBlock);
+		LayoutDetails::BuildBox(corner_box, Vector2f(containing_block.x), corner, BuildBoxMode::Unaligned);
 
 
 		corner_box.SetContent(Vector2f(scrollbars[VERTICAL].size, scrollbars[HORIZONTAL].size));
 		corner_box.SetContent(Vector2f(scrollbars[VERTICAL].size, scrollbars[HORIZONTAL].size));
 		corner->SetBox(corner_box);
 		corner->SetBox(corner_box);

+ 2 - 2
Source/Core/ElementUtilities.cpp

@@ -309,7 +309,7 @@ void ElementUtilities::FormatElement(Element* element, Vector2f containing_block
 
 
 void ElementUtilities::BuildBox(Box& box, Vector2f containing_block, Element* element, bool inline_element)
 void ElementUtilities::BuildBox(Box& box, Vector2f containing_block, Element* element, bool inline_element)
 {
 {
-	LayoutDetails::BuildBox(box, containing_block, element, inline_element ? BuildBoxMode::Inline : BuildBoxMode::Block);
+	LayoutDetails::BuildBox(box, containing_block, element, inline_element ? BuildBoxMode::Inline : BuildBoxMode::StretchFit);
 }
 }
 
 
 bool ElementUtilities::PositionElement(Element* element, Vector2f offset, PositionAnchor anchor)
 bool ElementUtilities::PositionElement(Element* element, Vector2f offset, PositionAnchor anchor)
@@ -324,7 +324,7 @@ bool ElementUtilities::PositionElement(Element* element, Vector2f offset, Positi
 	containing_block.y -= parent->GetElementScroll()->GetScrollbarSize(ElementScroll::HORIZONTAL);
 	containing_block.y -= parent->GetElementScroll()->GetScrollbarSize(ElementScroll::HORIZONTAL);
 
 
 	Box box;
 	Box box;
-	LayoutDetails::BuildBox(box, containing_block, element, BuildBoxMode::Block);
+	LayoutDetails::BuildBox(box, containing_block, element, BuildBoxMode::StretchFit);
 	if (box.GetSize().y < 0.f)
 	if (box.GetSize().y < 0.f)
 		box.SetContent(Vector2f(box.GetSize().x, containing_block.y));
 		box.SetContent(Vector2f(box.GetSize().x, containing_block.y));
 	element->SetBox(box);
 	element->SetBox(box);

+ 2 - 2
Source/Core/Layout/BlockFormattingContext.cpp

@@ -170,8 +170,8 @@ bool BlockFormattingContext::FormatBlockBox(BlockContainer* parent_container, El
 	const Vector2f containing_block = parent_container->GetContainingBlockSize(element->GetPosition());
 	const Vector2f containing_block = parent_container->GetContainingBlockSize(element->GetPosition());
 
 
 	const BuildBoxMode build_box_mode =
 	const BuildBoxMode build_box_mode =
-		(parent_container->GetFormattingMode().constraint == FormattingMode::Constraint::MaxContent ? BuildBoxMode::UnalignedBlock
-																									: BuildBoxMode::Block);
+		(parent_container->GetFormattingMode().constraint == FormattingMode::Constraint::MaxContent ? BuildBoxMode::Unaligned
+																									: BuildBoxMode::StretchFit);
 	Box box;
 	Box box;
 	LayoutDetails::BuildBox(box, containing_block, element, build_box_mode);
 	LayoutDetails::BuildBox(box, containing_block, element, build_box_mode);
 	float min_height, max_height;
 	float min_height, max_height;

+ 1 - 1
Source/Core/Layout/FlexFormattingContext.cpp

@@ -291,7 +291,7 @@ void FlexFormattingContext::Format(Vector2f& flex_resulting_content_size, Vector
 
 
 		FlexItem item = {};
 		FlexItem item = {};
 		item.element = element;
 		item.element = element;
-		LayoutDetails::BuildBox(item.box, flex_content_containing_block, element, BuildBoxMode::UnalignedBlock);
+		LayoutDetails::BuildBox(item.box, flex_content_containing_block, element, BuildBoxMode::Unaligned);
 
 
 		Style::LengthPercentageAuto item_main_size;
 		Style::LengthPercentageAuto item_main_size;
 
 

+ 15 - 2
Source/Core/Layout/FormattingContext.cpp

@@ -42,6 +42,18 @@
 
 
 namespace Rml {
 namespace Rml {
 
 
+static bool UsesFitContentSizeForAutoWidth(Element* element)
+{
+	// Whether to apply the fit-content sizing (shrink-to-fit width) algorithm to find the width of the element.
+	// See CSS 2.1 section 10.3.7 for when this should be applied.
+	const auto& computed = element->GetComputedValues();
+	const bool inset_auto = (computed.left().type == Style::Left::Auto || computed.right().type == Style::Right::Auto);
+	const bool absolutely_positioned = (computed.position() == Style::Position::Absolute || computed.position() == Style::Position::Fixed);
+
+	return (computed.float_() != Style::Float::None) || (absolutely_positioned && inset_auto) ||
+		(computed.display() == Style::Display::InlineBlock || computed.display() == Style::Display::InlineFlex);
+}
+
 FormattingContextType FormattingContext::GetFormattingContextType(Element* element)
 FormattingContextType FormattingContext::GetFormattingContextType(Element* element)
 {
 {
 	if (element->IsReplaced())
 	if (element->IsReplaced())
@@ -137,7 +149,8 @@ UniquePtr<LayoutBox> FormattingContext::FormatIndependent(ContainerBox* parent_c
 		}
 		}
 		else
 		else
 		{
 		{
-			LayoutDetails::BuildBox(box, containing_block, element, BuildBoxMode::ShrinkableBlock);
+			const BuildBoxMode build_box_mode = (UsesFitContentSizeForAutoWidth(element) ? BuildBoxMode::FitContent : BuildBoxMode::StretchFit);
+			LayoutDetails::BuildBox(box, containing_block, element, build_box_mode);
 
 
 			if (box.GetSize().x < 0.f)
 			if (box.GetSize().x < 0.f)
 			{
 			{
@@ -193,7 +206,7 @@ UniquePtr<LayoutBox> FormattingContext::FormatIndependent(ContainerBox* parent_c
 float FormattingContext::FormatFitContentWidth(ContainerBox* parent_container, Element* element, Vector2f containing_block)
 float FormattingContext::FormatFitContentWidth(ContainerBox* parent_container, Element* element, Vector2f containing_block)
 {
 {
 	Box box;
 	Box box;
-	LayoutDetails::BuildBox(box, containing_block, element, BuildBoxMode::UnalignedBlock);
+	LayoutDetails::BuildBox(box, containing_block, element, BuildBoxMode::Unaligned);
 
 
 	if (box.GetSize().x < 0.f)
 	if (box.GetSize().x < 0.f)
 	{
 	{

+ 24 - 20
Source/Core/Layout/LayoutDetails.cpp

@@ -88,7 +88,7 @@ void LayoutDetails::BuildBox(Box& box, Vector2f containing_block, Element* eleme
 
 
 	// Calculate the content area and constraints. 'auto' width and height are handled later.
 	// Calculate the content area and constraints. 'auto' width and height are handled later.
 	// For inline non-replaced elements, width and height are ignored, so we can skip the calculations.
 	// For inline non-replaced elements, width and height are ignored, so we can skip the calculations.
-	if (box_mode == BuildBoxMode::Block || box_mode == BuildBoxMode::ShrinkableBlock || box_mode == BuildBoxMode::UnalignedBlock || replaced_element)
+	if (box_mode == BuildBoxMode::StretchFit || box_mode == BuildBoxMode::FitContent || box_mode == BuildBoxMode::Unaligned || replaced_element)
 	{
 	{
 		content_area.x = ResolveValueOr(computed.width(), containing_block.x, -1.f);
 		content_area.x = ResolveValueOr(computed.width(), containing_block.x, -1.f);
 		content_area.y = ResolveValueOr(computed.height(), containing_block.y, -1.f);
 		content_area.y = ResolveValueOr(computed.height(), containing_block.y, -1.f);
@@ -185,7 +185,7 @@ void LayoutDetails::BuildAutoMarginsForBlockBox(Box& box, Vector2f containing_bl
 	const Vector2f min_size = {0, 0};
 	const Vector2f min_size = {0, 0};
 	const Vector2f max_size = {FLT_MAX, FLT_MAX};
 	const Vector2f max_size = {FLT_MAX, FLT_MAX};
 
 
-	BuildBoxSizeAndMargins(box, min_size, max_size, containing_block, element, BuildBoxMode::Block);
+	BuildBoxSizeAndMargins(box, min_size, max_size, containing_block, element, BuildBoxMode::StretchFit);
 	RMLUI_ASSERT(box.GetSize() == initial_content_size);
 	RMLUI_ASSERT(box.GetSize() == initial_content_size);
 }
 }
 
 
@@ -194,7 +194,7 @@ void LayoutDetails::BuildBoxSizeAndMargins(Box& box, Vector2f min_size, Vector2f
 {
 {
 	const ComputedValues& computed = element->GetComputedValues();
 	const ComputedValues& computed = element->GetComputedValues();
 
 
-	if (box_mode == BuildBoxMode::Inline || box_mode == BuildBoxMode::UnalignedBlock)
+	if (box_mode == BuildBoxMode::Inline || box_mode == BuildBoxMode::Unaligned)
 	{
 	{
 		// For inline elements, their calculations are straightforward. No worrying about auto margins and dimensions, etc.
 		// For inline elements, their calculations are straightforward. No worrying about auto margins and dimensions, etc.
 		// Evaluate the margins. Any declared as 'auto' will resolve to 0.
 		// Evaluate the margins. Any declared as 'auto' will resolve to 0.
@@ -206,7 +206,7 @@ void LayoutDetails::BuildBoxSizeAndMargins(Box& box, Vector2f min_size, Vector2f
 	else
 	else
 	{
 	{
 		// The element is block, so we need to run the box through the ringer to potentially evaluate auto margins and dimensions.
 		// The element is block, so we need to run the box through the ringer to potentially evaluate auto margins and dimensions.
-		BuildBoxWidth(box, computed, min_size.x, max_size.x, containing_block, element);
+		BuildBoxWidth(box, computed, min_size.x, max_size.x, containing_block, element, box_mode);
 		BuildBoxHeight(box, computed, min_size.y, max_size.y, containing_block.y);
 		BuildBoxHeight(box, computed, min_size.y, max_size.y, containing_block.y);
 	}
 	}
 }
 }
@@ -219,7 +219,7 @@ void LayoutDetails::ClampSizeAndBuildAutoMarginsForBlockWidth(Box& box, Vector2f
 	float min_width = 0.f;
 	float min_width = 0.f;
 	float max_width = FLT_MAX;
 	float max_width = FLT_MAX;
 	GetMinMaxWidth(min_width, max_width, computed, box, containing_block.x);
 	GetMinMaxWidth(min_width, max_width, computed, box, containing_block.x);
-	BuildBoxWidth(box, computed, min_width, max_width, containing_block, element);
+	BuildBoxWidth(box, computed, min_width, max_width, containing_block, element, BuildBoxMode::StretchFit);
 }
 }
 
 
 ComputedAxisSize LayoutDetails::BuildComputedHorizontalSize(const ComputedValues& computed)
 ComputedAxisSize LayoutDetails::BuildComputedHorizontalSize(const ComputedValues& computed)
@@ -344,7 +344,7 @@ Vector2f LayoutDetails::CalculateSizeForReplacedElement(const Vector2f specified
 }
 }
 
 
 void LayoutDetails::BuildBoxWidth(Box& box, const ComputedValues& computed, float min_width, float max_width, Vector2f containing_block,
 void LayoutDetails::BuildBoxWidth(Box& box, const ComputedValues& computed, float min_width, float max_width, Vector2f containing_block,
-	Element* element)
+	Element* element, BuildBoxMode box_mode)
 {
 {
 	Vector2f content_area = box.GetSize();
 	Vector2f content_area = box.GetSize();
 
 
@@ -368,26 +368,20 @@ void LayoutDetails::BuildBoxWidth(Box& box, const ComputedValues& computed, floa
 		}
 		}
 	}
 	}
 
 
-	const bool absolutely_positioned = (computed.position() == Style::Position::Absolute || computed.position() == Style::Position::Fixed);
-	const bool inset_auto = (computed.left().type == Style::Left::Auto || computed.right().type == Style::Right::Auto);
-	const bool width_auto = (content_area.x < 0);
-
 	auto GetInsetWidth = [&] {
 	auto GetInsetWidth = [&] {
 		// For absolutely positioned elements (and only those), the 'left' and 'right' values are part of the box's width constraint.
 		// For absolutely positioned elements (and only those), the 'left' and 'right' values are part of the box's width constraint.
+		const bool absolutely_positioned = (computed.position() == Style::Position::Absolute || computed.position() == Style::Position::Fixed);
 		if (absolutely_positioned)
 		if (absolutely_positioned)
 			return ResolveValue(computed.left(), containing_block.x) + ResolveValue(computed.right(), containing_block.x);
 			return ResolveValue(computed.left(), containing_block.x) + ResolveValue(computed.right(), containing_block.x);
 		return 0.f;
 		return 0.f;
 	};
 	};
 
 
 	// If the width is set to auto, we need to calculate the width.
 	// If the width is set to auto, we need to calculate the width.
-	if (width_auto)
+	if (content_area.x < 0)
 	{
 	{
-		// Apply the shrink-to-fit algorithm here to find the width of the element.
-		// See CSS 2.1 section 10.3.7 for when this should be applied.
-		const bool shrink_to_fit = ((computed.float_() != Style::Float::None) || (absolutely_positioned && inset_auto) ||
-			(computed.display() == Style::Display::InlineBlock || computed.display() == Style::Display::InlineFlex));
-
-		if (!shrink_to_fit)
+		switch (box_mode)
+		{
+		case BuildBoxMode::StretchFit:
 		{
 		{
 			// The width is set to fill the remaining space of the containing block, if the available space is definite.
 			// The width is set to fill the remaining space of the containing block, if the available space is definite.
 			if (containing_block.x >= 0.f)
 			if (containing_block.x >= 0.f)
@@ -396,9 +390,19 @@ void LayoutDetails::BuildBoxWidth(Box& box, const ComputedValues& computed, floa
 				content_area.x = Math::Max(containing_block.x - accumulated_edges, 0.f);
 				content_area.x = Math::Max(containing_block.x - accumulated_edges, 0.f);
 			}
 			}
 		}
 		}
-		else
+		break;
+		case BuildBoxMode::FitContent:
+		{
+			// Leave the width negative to indicate it should have its fit-content width evaluated by the caller.
+		}
+		break;
+		case BuildBoxMode::Unaligned:
+		case BuildBoxMode::Inline:
 		{
 		{
-			// Leave width negative to indicate it should have its shrink-to-fit width evaluated.
+			// Not allowed here.
+			RMLUI_ERROR;
+		}
+		break;
 		}
 		}
 	}
 	}
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
@@ -422,7 +426,7 @@ void LayoutDetails::BuildBoxWidth(Box& box, const ComputedValues& computed, floa
 		box.SetContent(content_area);
 		box.SetContent(content_area);
 
 
 		if (num_auto_margins > 0)
 		if (num_auto_margins > 0)
-			BuildBoxWidth(box, computed, min_width, max_width, containing_block, element);
+			BuildBoxWidth(box, computed, min_width, max_width, containing_block, element, box_mode);
 	}
 	}
 	else
 	else
 	{
 	{

+ 8 - 8
Source/Core/Layout/LayoutDetails.h

@@ -53,12 +53,11 @@ struct ComputedAxisSize {
 };
 };
 
 
 enum class BuildBoxMode {
 enum class BuildBoxMode {
-	Block, // Sets edges and size if available, auto width uses stretch-fit width (never shrink-to-fit), auto margins are used for alignment.
-	ShrinkableBlock, // Like block, but auto width returns -1 when shrink-to-fit width should be applied, auto margins should then be re-evaluated.
-	// TODO: Block and ShrinkableBlock is the same right now. Remove the latter - or - differentiate between fit-content
-	//       and stretch-fit size, placing the "can we shrink" question on the caller.
-	UnalignedBlock, // Like block, but auto width returns -1, and auto margins are always resolved to zero.
-	Inline,         // Sets edges, ignores width, height, and auto margins.
+	StretchFit, // Sets edges and size if available, auto width fills the available width, auto margins are used for alignment.
+	FitContent, // Sets edges and size if available, auto width returns -1 to indicate to the caller that fit-content should be applied, auto margins
+	            // should then be re-evaluated once sized.
+	Unaligned,  // Sets edges and size if available, auto width returns -1, auto margins are always resolved to zero.
+	Inline,     // Sets edges, ignores width, height, and auto margins.
 };
 };
 
 
 /**
 /**
@@ -138,8 +137,9 @@ private:
 	/// @param[in] max_width The maximum content width of the element.
 	/// @param[in] max_width The maximum content width of the element.
 	/// @param[in] containing_block The size of the containing block.
 	/// @param[in] containing_block The size of the containing block.
 	/// @param[in] element The element the box is being generated for.
 	/// @param[in] element The element the box is being generated for.
-	static void BuildBoxWidth(Box& box, const ComputedValues& computed, float min_width, float max_width, Vector2f containing_block,
-		Element* element);
+	/// @param[in] box_mode The mode which determines how the box is built.
+	static void BuildBoxWidth(Box& box, const ComputedValues& computed, float min_width, float max_width, Vector2f containing_block, Element* element,
+		BuildBoxMode box_mode);
 	/// Builds the block-specific height and vertical margins of a Box.
 	/// Builds the block-specific height and vertical margins of a Box.
 	/// @param[in,out] box The box to generate. The padding and borders must be set on the box already. The content area is used instead of the height
 	/// @param[in,out] box The box to generate. The padding and borders must be set on the box already. The content area is used instead of the height
 	/// property, and -1 means auto height.
 	/// property, and -1 means auto height.

+ 1 - 1
Source/Core/Layout/TableFormattingContext.cpp

@@ -205,7 +205,7 @@ void TableFormattingContext::InitializeCellBoxes(BoxList& cells, const TrackBoxL
 		Box& box = cells[i];
 		Box& box = cells[i];
 
 
 		// Determine the cell's box for formatting later, we may get an indefinite (-1) vertical content size.
 		// Determine the cell's box for formatting later, we may get an indefinite (-1) vertical content size.
-		LayoutDetails::BuildBox(box, table_initial_content_size, grid.cells[i].element_cell, BuildBoxMode::UnalignedBlock);
+		LayoutDetails::BuildBox(box, table_initial_content_size, grid.cells[i].element_cell, BuildBoxMode::Unaligned);
 
 
 		// Determine the cell's content width. Include any spanning columns in the cell width.
 		// Determine the cell's content width. Include any spanning columns in the cell width.
 		const float cell_border_width = GetSpanningCellBorderSize(columns, grid.cells[i].column_begin, grid.cells[i].column_last);
 		const float cell_border_width = GetSpanningCellBorderSize(columns, grid.cells[i].column_begin, grid.cells[i].column_last);

+ 4 - 4
Source/Core/WidgetScroll.cpp

@@ -210,7 +210,7 @@ void WidgetScroll::FormatElements(const Vector2f containing_block, float slider_
 
 
 	// Build the box for the containing slider element.
 	// Build the box for the containing slider element.
 	Box parent_box;
 	Box parent_box;
-	LayoutDetails::BuildBox(parent_box, containing_block, parent, BuildBoxMode::UnalignedBlock);
+	LayoutDetails::BuildBox(parent_box, containing_block, parent, BuildBoxMode::Unaligned);
 	slider_length -= orientation == VERTICAL
 	slider_length -= orientation == VERTICAL
 		? (parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Top) + parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Bottom))
 		? (parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Top) + parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Bottom))
 		: (parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Left) + parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Right));
 		: (parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Left) + parent_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Right));
@@ -224,7 +224,7 @@ void WidgetScroll::FormatElements(const Vector2f containing_block, float slider_
 
 
 	// Generate the initial dimensions for the track. It'll need to be cut down to fit the arrows.
 	// Generate the initial dimensions for the track. It'll need to be cut down to fit the arrows.
 	Box track_box;
 	Box track_box;
-	LayoutDetails::BuildBox(track_box, parent_box.GetSize(), track, BuildBoxMode::Block);
+	LayoutDetails::BuildBox(track_box, parent_box.GetSize(), track, BuildBoxMode::StretchFit);
 	content = track_box.GetSize();
 	content = track_box.GetSize();
 	content[length_axis] = slider_length -= orientation == VERTICAL
 	content[length_axis] = slider_length -= orientation == VERTICAL
 		? (track_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Top) + track_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Bottom))
 		? (track_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Top) + track_box.GetCumulativeEdge(BoxArea::Content, BoxEdge::Bottom))
@@ -238,7 +238,7 @@ void WidgetScroll::FormatElements(const Vector2f containing_block, float slider_
 	for (int i = 0; i < 2; i++)
 	for (int i = 0; i < 2; i++)
 	{
 	{
 		Box arrow_box;
 		Box arrow_box;
-		LayoutDetails::BuildBox(arrow_box, parent_box.GetSize(), arrows[i], BuildBoxMode::Block);
+		LayoutDetails::BuildBox(arrow_box, parent_box.GetSize(), arrows[i], BuildBoxMode::StretchFit);
 
 
 		// Clamp the size to (0, 0).
 		// Clamp the size to (0, 0).
 		Vector2f arrow_size = arrow_box.GetSize();
 		Vector2f arrow_size = arrow_box.GetSize();
@@ -292,7 +292,7 @@ void WidgetScroll::FormatElements(const Vector2f containing_block, float slider_
 void WidgetScroll::FormatBar()
 void WidgetScroll::FormatBar()
 {
 {
 	Box bar_box;
 	Box bar_box;
-	LayoutDetails::BuildBox(bar_box, parent->GetBox().GetSize(), bar, BuildBoxMode::Block);
+	LayoutDetails::BuildBox(bar_box, parent->GetBox().GetSize(), bar, BuildBoxMode::StretchFit);
 
 
 	const auto& computed = bar->GetComputedValues();
 	const auto& computed = bar->GetComputedValues();