Skip to content

Commit

Permalink
Implement absolute positioning
Browse files Browse the repository at this point in the history
Shrink-to-fit size is missing, absolute positioning in inline formatting contexts is
missing. There are probably off-by-some-amount-of-pixels bugs lying around.
  • Loading branch information
nox committed Apr 3, 2019
1 parent 6ddce73 commit cea21bb
Show file tree
Hide file tree
Showing 11 changed files with 537 additions and 32 deletions.
6 changes: 6 additions & 0 deletions tests/reftests/abspos-ref.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<body style="margin:0px">
<div style="background-color: green; padding-left: 70px; padding-top: 20px; width: 130px; height: 80px">
<div style="background-color: red; width: 50px; height: 30px"></div>
</div>
</body>
7 changes: 7 additions & 0 deletions tests/reftests/abspos.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!doctype html>
<link rel=match href="abspos-ref.html">
<body style="margin:0px">
<div style="background-color: green; width: 200px; height: 100px">
<div style="background-color: red; position: absolute; top: 20px; left: 70px; width: 50px; height: 30px"></div>
</div>
</body>
15 changes: 15 additions & 0 deletions victor/src/geom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ where
}
}
}

impl<T: Clone> physical::Vec2<T> {
pub fn size_to_flow_relative(&self, mode: (WritingMode, Direction)) -> flow_relative::Vec2<T> {
// https://drafts.csswg.org/css-writing-modes/#logical-to-physical
Expand All @@ -75,6 +76,20 @@ impl<T: Clone> physical::Vec2<T> {
}
}

impl<T> Add<&'_ flow_relative::Vec2<T>> for &'_ flow_relative::Vec2<T>
where
T: Add<Output = T> + Copy,
{
type Output = flow_relative::Vec2<T>;

fn add(self, other: &'_ flow_relative::Vec2<T>) -> Self::Output {
flow_relative::Vec2 {
inline: self.inline + other.inline,
block: self.block + other.block,
}
}
}

impl<T: Clone> flow_relative::Vec2<T> {
pub fn size_to_physical(&self, mode: (WritingMode, Direction)) -> physical::Vec2<T> {
// https://drafts.csswg.org/css-writing-modes/#logical-to-physical
Expand Down
71 changes: 60 additions & 11 deletions victor/src/layout/boxes/generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::*;
use crate::dom;
use crate::fonts::BITSTREAM_VERA_SANS;
use crate::layout::Take;
use crate::style::values::{Display, DisplayInside, DisplayOutside};
use crate::style::values::{Display, DisplayInside, DisplayOutside, Position};
use crate::style::{style_for_element, StyleSet, StyleSetBuilder};
use rayon::iter::{IntoParallelIterator, ParallelIterator};

Expand Down Expand Up @@ -38,6 +38,10 @@ enum IntermediateBlockLevelBox {
style: Arc<ComputedValues>,
contents: IntermediateBlockContainer,
},
AbsolutelyPositionedBox {
style: Arc<ComputedValues>,
element: dom::NodeId,
},
}

/// A block container that may still have to be constructed.
Expand Down Expand Up @@ -216,16 +220,28 @@ impl<'a> BlockContainerBuilder<'a> {
descendant,
parent_style.map(|style| &**style),
);
match descendant_style.box_.display {
Display::None => self.move_to_next_sibling(descendant),
Display::Other {
outside: DisplayOutside::Inline,
inside: DisplayInside::Flow,
} => self.handle_inline_level_element(descendant, descendant_style),
Display::Other {
outside: DisplayOutside::Block,
inside: DisplayInside::Flow,
} => self.handle_block_level_element(descendant, descendant_style),
match (
descendant_style.box_.display,
descendant_style.box_.position,
) {
(Display::None, _) => self.move_to_next_sibling(descendant),
(_, Position::Absolute) => {
self.handle_absolutely_positioned_element(descendant, descendant_style)
}
(
Display::Other {
outside: DisplayOutside::Inline,
inside: DisplayInside::Flow,
},
_,
) => self.handle_inline_level_element(descendant, descendant_style),
(
Display::Other {
outside: DisplayOutside::Block,
inside: DisplayInside::Flow,
},
_,
) => self.handle_block_level_element(descendant, descendant_style),
}
}

Expand Down Expand Up @@ -318,6 +334,29 @@ impl<'a> BlockContainerBuilder<'a> {
self.move_to_next_sibling(descendant)
}

fn handle_absolutely_positioned_element(
&mut self,
descendant: dom::NodeId,
descendant_style: Arc<ComputedValues>,
) -> Option<dom::NodeId> {
if self
.ongoing_inline_formatting_context
.inline_level_boxes
.is_empty()
&& self.ongoing_inline_level_box_stack.is_empty()
{
self.block_level_boxes
.push(IntermediateBlockLevelBox::AbsolutelyPositionedBox {
style: descendant_style,
element: descendant,
})
} else {
// FIXME(nox): Handle absolutely-positioned elements in
// inline boxes.
}
self.move_to_next_sibling(descendant)
}

fn move_to_next_sibling(&mut self, descendant: dom::NodeId) -> Option<dom::NodeId> {
let mut descendant_node = &self.context.document[descendant];
if let Some(next_sibling) = descendant_node.next_sibling {
Expand Down Expand Up @@ -411,6 +450,16 @@ impl IntermediateBlockLevelBox {
style,
}
}
IntermediateBlockLevelBox::AbsolutelyPositionedBox { style, element } => {
BlockLevelBox::AbsolutelyPositionedBox {
contents: BlockFormattingContext(BlockContainerBuilder::build(
context,
element,
Some(&style),
)),
style: style,
}
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions victor/src/layout/boxes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ pub(super) enum BlockLevelBox {
style: Arc<ComputedValues>,
contents: BlockContainer,
},
AbsolutelyPositionedBox {
style: Arc<ComputedValues>,
contents: BlockFormattingContext,
},
// Other {
// style: Arc<ComputedValues>,
// contents: FormattingContext,
Expand Down
26 changes: 25 additions & 1 deletion victor/src/layout/fragments/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::geom::flow_relative::{Rect, Sides};
use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::geom::Length;
use crate::style::ComputedValues;
use crate::text::ShapedSegment;
Expand Down Expand Up @@ -30,6 +30,30 @@ pub(crate) struct TextFragment {
}

impl BoxFragment {
pub fn zero_sized(style: Arc<ComputedValues>) -> Self {
let zero_vec = Vec2 {
inline: Length::zero(),
block: Length::zero(),
};
let zero_sides = Sides {
inline_start: Length::zero(),
inline_end: Length::zero(),
block_start: Length::zero(),
block_end: Length::zero(),
};
Self {
style,
children: vec![],
content_rect: Rect {
start_corner: zero_vec.clone(),
size: zero_vec,
},
padding: zero_sides.clone(),
border: zero_sides.clone(),
margin: zero_sides,
}
}

pub fn border_rect(&self) -> Rect<Length> {
self.content_rect
.inflate(&self.padding)
Expand Down
Loading

0 comments on commit cea21bb

Please sign in to comment.