Skip to content

Commit

Permalink
web/core: Represent float property as an Option<Side>
Browse files Browse the repository at this point in the history
This makes sense intuitively, because when handling floats
we first check whether the box is even floating (builder.rs)
but don't want to worry about the float:none case afterwards.
  • Loading branch information
simonwuelker committed Dec 9, 2023
1 parent 959ed65 commit d86490d
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 40 deletions.
2 changes: 1 addition & 1 deletion crates/web/core/properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"specification": "https://drafts.csswg.org/css2/#propdef-float",
"inherited": false,
"value": "Float",
"initial": "Float::None"
"initial": "Float::default()"
},
{
"name": "font-family",
Expand Down
13 changes: 4 additions & 9 deletions crates/web/core/src/css/layout/flow/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
BlockContainer, BlockLevelBox, InFlowBlockBox, InlineBox, InlineFormattingContext,
InlineLevelBox,
},
values, ComputedStyle, StyleComputer,
ComputedStyle, StyleComputer,
},
dom::{dom_objects, DomPtr},
};
Expand Down Expand Up @@ -162,8 +162,9 @@ impl<'stylesheets, 'parent_style> BoxTreeBuilder<'stylesheets, 'parent_style> {
let content = BoxTreeBuilder::build(node.clone(), self.style_computer, &style);

let position = style.position();
let block_box = match style.float() {
values::Float::None => {
let block_box = match style.float().side() {
Some(side) => float::FloatingBox::new(node, style, side, content).into(),
None => {
if position.is_absolute() || position.is_fixed() {
AbsolutelyPositionedBox {
style,
Expand All @@ -175,12 +176,6 @@ impl<'stylesheets, 'parent_style> BoxTreeBuilder<'stylesheets, 'parent_style> {
InFlowBlockBox::new(style, Some(node), content).into()
}
},
values::Float::Left => {
float::FloatingBox::new(node, style, float::Side::Left, content).into()
},
values::Float::Right => {
float::FloatingBox::new(node, style, float::Side::Right, content).into()
},
};
self.block_level_boxes.push(block_box);
}
Expand Down
36 changes: 15 additions & 21 deletions crates/web/core/src/css/layout/flow/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
values::{
self,
length::{self, Length},
AutoOr, PercentageOr,
AutoOr, FloatSide, PercentageOr,
},
},
dom::{dom_objects, DomPtr},
Expand All @@ -28,7 +28,7 @@ use super::BlockContainer;
pub struct FloatingBox {
pub node: DomPtr<dom_objects::Node>,
pub style: ComputedStyle,
pub side: Side,
pub side: FloatSide,
pub contents: BlockContainer,
}

Expand All @@ -37,7 +37,7 @@ impl FloatingBox {
pub fn new(
node: DomPtr<dom_objects::Node>,
style: ComputedStyle,
side: Side,
side: FloatSide,
contents: BlockContainer,
) -> Self {
Self {
Expand Down Expand Up @@ -223,16 +223,16 @@ impl FloatContext {
/// Place a float in a given position.
///
/// `y_offset` describes the offset within the height of the content band specified by `content_band_index`.
fn place_float(&mut self, margin_area: Size<Pixels>, side: Side, placement: Placement) {
fn place_float(&mut self, margin_area: Size<Pixels>, side: FloatSide, placement: Placement) {
// Split the content band in up to three new bands
let old_content_band = self.content_bands.remove(placement.band_index);
let (new_inset_left, new_inset_right) = match side {
Side::Left => {
FloatSide::Left => {
let inset_left =
Some(old_content_band.inset_left.unwrap_or_default() + margin_area.width);
(inset_left, old_content_band.inset_right)
},
Side::Right => {
FloatSide::Right => {
let inset_right =
Some(old_content_band.inset_right.unwrap_or_default() + margin_area.width);
(old_content_band.inset_left, inset_right)
Expand Down Expand Up @@ -272,16 +272,16 @@ impl FloatContext {
self.lower_float_ceiling(placement.position.y);

match side {
Side::Left => {
FloatSide::Left => {
self.lowest_float_left = placement.position.y + margin_area.height;
},
Side::Right => {
FloatSide::Right => {
self.lowest_float_right = placement.position.y + margin_area.height;
},
}
}

fn find_position_for_float(&self, float_width: Pixels, side: Side) -> Placement {
fn find_position_for_float(&self, float_width: Pixels, side: FloatSide) -> Placement {
debug_assert!(!self.content_bands.is_empty());

let mut cursor = Pixels::ZERO;
Expand Down Expand Up @@ -312,8 +312,8 @@ impl FloatContext {
let chosen_band = &self.content_bands[band_to_place_float_in];
let y_position = cmp::max(cursor, self.float_ceiling);
let x_position = match side {
Side::Left => chosen_band.inset_left.unwrap_or_default(),
Side::Right => {
FloatSide::Left => chosen_band.inset_left.unwrap_or_default(),
FloatSide::Right => {
self.containing_block.width()
- float_width
- chosen_band.inset_right.unwrap_or_default()
Expand All @@ -335,7 +335,7 @@ impl FloatContext {
pub fn find_position_and_place_float_box(
&mut self,
margin_area: Size<Pixels>,
side: Side,
side: FloatSide,
) -> Vec2D<Pixels> {
let placement = self.find_position_for_float(margin_area.width, side);
self.place_float(margin_area, side, placement);
Expand All @@ -350,12 +350,6 @@ struct Placement {
offset_in_band: Pixels,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Side {
Left,
Right,
}

/// A rectangular area where content may be placed
#[derive(Clone, Debug)]
struct ContentBand {
Expand All @@ -368,16 +362,16 @@ impl ContentBand {
fn box_fits(
&self,
box_width: Pixels,
place_on_side: Side,
place_on_side: FloatSide,
width_of_containing_block: Pixels,
) -> bool {
// The algorithm is the same for left- and right-floating boxes.
// So instead of duplicating code, we only implement it for left-floating boxes
// and switch the insets on the two sides if necessary

let (this_side, opposing_side) = match place_on_side {
Side::Left => (self.inset_left, self.inset_right),
Side::Right => (self.inset_right, self.inset_left),
FloatSide::Left => (self.inset_left, self.inset_right),
FloatSide::Right => (self.inset_right, self.inset_left),
};

let position = this_side.unwrap_or_default();
Expand Down
27 changes: 19 additions & 8 deletions crates/web/core/src/css/values/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,33 @@ use crate::{
};

/// <https://drafts.csswg.org/css2/#propdef-float>
#[derive(Clone, Copy, Debug)]
pub enum Float {
#[derive(Clone, Copy, Debug, Default)]
pub struct Float {
side: Option<FloatSide>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FloatSide {
Left,
Right,
None,
}

impl Float {
#[must_use]
pub fn side(&self) -> Option<FloatSide> {
self.side
}
}

impl<'a> CSSParse<'a> for Float {
fn parse(parser: &mut Parser<'a>) -> Result<Self, ParseError> {
let value = match parser.expect_identifier()? {
static_interned!("left") => Self::Left,
static_interned!("right") => Self::Right,
static_interned!("none") => Self::None,
let side = match parser.expect_identifier()? {
static_interned!("left") => Some(FloatSide::Left),
static_interned!("right") => Some(FloatSide::Right),
static_interned!("none") => None,
_ => return Err(ParseError),
};
Ok(value)
Ok(Self { side })
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/web/core/src/css/values/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use background_color::BackgroundColor;
pub use border::{Border, LineStyle, LineWidth};
pub use color::Color;
pub use display::Display;
pub use float::{Clear, Float};
pub use float::{Clear, Float, FloatSide};
pub use font_family::{FontFamily, FontName};
pub use font_size::FontSize;
pub use font_style::FontStyle;
Expand Down

0 comments on commit d86490d

Please sign in to comment.