Skip to content

Commit

Permalink
Implement legacy text alignment (#698)
Browse files Browse the repository at this point in the history
* Add TextAlign style

* Add legacy text-align support to the test generator

* Implement legacy text alignment

* Fix docs
  • Loading branch information
nicoburns authored Jul 29, 2024
1 parent 5e4dcf1 commit 42f75c6
Show file tree
Hide file tree
Showing 14 changed files with 836 additions and 9 deletions.
11 changes: 11 additions & 0 deletions scripts/gentest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,16 @@ fn generate_node(ident: &str, node: &Value) -> TokenStream {
(quote!(), quote!())
};

let text_align = match style["textAlign"] {
Value::String(ref value) => match value.as_ref() {
"-webkit-left" => quote!(text_align: taffy::style::TextAlign::LegacyLeft,),
"-webkit-right" => quote!(text_align: taffy::style::TextAlign::LegacyRight,),
"-webkit-center" => quote!(text_align: taffy::style::TextAlign::LegacyCenter,),
_ => quote!(),
},
_ => quote!(),
};

let align_items = match style["alignItems"] {
Value::String(ref value) => match value.as_ref() {
"start" => quote!(align_items: Some(taffy::style::AlignItems::Start),),
Expand Down Expand Up @@ -618,6 +628,7 @@ fn generate_node(ident: &str, node: &Value) -> TokenStream {
#box_sizing
#direction
#position
#text_align
#flex_direction
#flex_wrap
#overflow
Expand Down
4 changes: 3 additions & 1 deletion scripts/gentest/test_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,12 @@ function describeElement(e) {

position: parseEnum(e.style.position),
direction: parseEnum(e.style.direction),
flexDirection: parseEnum(e.style.flexDirection),

writingMode: parseEnum(e.style.writingMode),

textAlign: parseEnum(e.style.textAlign),

flexDirection: parseEnum(e.style.flexDirection),
flexWrap: parseEnum(e.style.flexWrap),
overflowX: parseEnum(e.style.overflowX),
overflowY: parseEnum(e.style.overflowY),
Expand Down
23 changes: 21 additions & 2 deletions src/compute/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::util::sys::f32_max;
use crate::util::sys::Vec;
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
use crate::{BoxGenerationMode, BoxSizing, LayoutBlockContainer};
use crate::{BlockContainerStyle, BoxGenerationMode, BoxSizing, LayoutBlockContainer, TextAlign};

#[cfg(feature = "content_size")]
use super::common::content_size::compute_content_size_contribution;
Expand Down Expand Up @@ -190,6 +190,8 @@ fn compute_inner(tree: &mut impl LayoutBlockContainer, node_id: NodeId, inputs:
|| matches!(size.height, Some(h) if h > 0.0)
|| matches!(min_size.height, Some(h) if h > 0.0);

let text_align = style.text_align();

drop(style);

// 1. Generate items
Expand Down Expand Up @@ -219,6 +221,7 @@ fn compute_inner(tree: &mut impl LayoutBlockContainer, node_id: NodeId, inputs:
container_outer_width,
content_box_inset,
resolved_content_box_inset,
text_align,
own_margins_collapse_with_children,
);
let container_outer_height = known_dimensions
Expand Down Expand Up @@ -383,6 +386,7 @@ fn perform_final_layout_on_in_flow_children(
container_outer_width: f32,
content_box_inset: Rect<f32>,
resolved_content_box_inset: Rect<f32>,
text_align: TextAlign,
own_margins_collapse_with_children: Line<bool>,
) -> (Size<f32>, f32, CollapsibleMarginSet, CollapsibleMarginSet) {
// Resolve container_inner_width for sizing child nodes using initial content_box_inset
Expand Down Expand Up @@ -469,11 +473,26 @@ fn perform_final_layout_on_in_flow_children(
x: resolved_content_box_inset.left,
y: committed_y_offset + active_collapsible_margin_set.resolve(),
};
let location = Point {
let mut location = Point {
x: resolved_content_box_inset.left + inset_offset.x + resolved_margin.left,
y: committed_y_offset + inset_offset.y + y_margin_offset,
};

// Apply alignment
let item_outer_width = item_layout.size.width + resolved_margin.horizontal_axis_sum();
if item_outer_width < container_inner_width {
match text_align {
TextAlign::Auto => {
// Do nothing
}
TextAlign::LegacyLeft => {
// Do nothing. Left aligned by default.
}
TextAlign::LegacyRight => location.x += container_inner_width - item_outer_width,
TextAlign::LegacyCenter => location.x += (container_inner_width - item_outer_width) / 2.0,
}
}

let scrollbar_size = Size {
width: if item.overflow.y == Overflow::Scroll { item.scrollbar_width } else { 0.0 },
height: if item.overflow.x == Overflow::Scroll { item.scrollbar_width } else { 0.0 },
Expand Down
2 changes: 1 addition & 1 deletion src/compute/flexbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ struct AlgoConstants {
inner_container_size: Size<f32>,
}

/// Computes the layout of [`LayoutPartialTree`] according to the flexbox algorithm
/// Computes the layout of a box according to the flexbox algorithm
pub fn compute_flexbox_layout(
tree: &mut impl LayoutFlexboxContainer,
node: NodeId,
Expand Down
26 changes: 26 additions & 0 deletions src/style/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Style types for Block layout
use crate::{CoreStyle, Style};

/// The set of styles required for a CSS Grid item (child of a CSS Grid container)
pub trait BlockContainerStyle: CoreStyle {
/// Defines which row in the grid the item should start and end at
#[inline(always)]
fn text_align(&self) -> TextAlign {
Style::DEFAULT.text_align
}
}

/// Used by block layout to implement the legacy behaviour of `<center>` and `<div align="left | right | center">`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TextAlign {
/// No special legacy text align behaviour.
#[default]
Auto,
/// Corresponds to `-webkit-left` or `-moz-left` in browsers
LegacyLeft,
/// Corresponds to `-webkit-right` or `-moz-right` in browsers
LegacyRight,
/// Corresponds to `-webkit-center` or `-moz-center` in browsers
LegacyCenter,
}
40 changes: 36 additions & 4 deletions src/style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@
mod alignment;
mod dimension;

#[cfg(feature = "block_layout")]
mod block;
#[cfg(feature = "flexbox")]
mod flex;
#[cfg(feature = "grid")]
mod grid;

pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto};

#[cfg(feature = "block_layout")]
pub use self::block::{BlockContainerStyle, TextAlign};
#[cfg(feature = "flexbox")]
pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};

#[cfg(feature = "grid")]
mod grid;
#[cfg(feature = "grid")]
pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement};
#[cfg(feature = "grid")]
pub use self::grid::{
GridAutoFlow, GridContainerStyle, GridItemStyle, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction,
MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction,
};

use crate::geometry::{Point, Rect, Size};

#[cfg(feature = "grid")]
Expand Down Expand Up @@ -394,13 +398,20 @@ pub struct Style {
#[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
pub gap: Size<LengthPercentage>,

// Flexbox properties
// Block container properties
/// How items elements should aligned in the inline axis
#[cfg(feature = "block_layout")]
pub text_align: TextAlign,

// Flexbox container properties
/// Which direction does the main axis flow in?
#[cfg(feature = "flexbox")]
pub flex_direction: FlexDirection,
/// Should elements wrap, or stay in a single line?
#[cfg(feature = "flexbox")]
pub flex_wrap: FlexWrap,

// Flexbox item properties
/// Sets the initial main axis size of the item
#[cfg(feature = "flexbox")]
pub flex_basis: Dimension,
Expand Down Expand Up @@ -472,6 +483,9 @@ impl Style {
align_content: None,
#[cfg(any(feature = "flexbox", feature = "grid"))]
justify_content: None,
// Block
#[cfg(feature = "block_layout")]
text_align: TextAlign::Auto,
// Flexbox
#[cfg(feature = "flexbox")]
flex_direction: FlexDirection::Row,
Expand Down Expand Up @@ -629,6 +643,22 @@ impl<T: CoreStyle> CoreStyle for &'_ T {
}
}

#[cfg(feature = "block_layout")]
impl BlockContainerStyle for &Style {
#[inline(always)]
fn text_align(&self) -> TextAlign {
self.text_align
}
}

#[cfg(feature = "block_layout")]
impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
#[inline(always)]
fn text_align(&self) -> TextAlign {
(*self).text_align()
}
}

#[cfg(feature = "flexbox")]
impl FlexboxContainerStyle for &Style {
#[inline(always)]
Expand Down Expand Up @@ -890,6 +920,8 @@ mod tests {
padding: Rect::zero(),
border: Rect::zero(),
gap: Size::zero(),
#[cfg(feature = "block_layout")]
text_align: Default::default(),
#[cfg(feature = "flexbox")]
flex_grow: 0.0,
#[cfg(feature = "flexbox")]
Expand Down
4 changes: 3 additions & 1 deletion src/tree/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ use crate::style::{AvailableSpace, CoreStyle};
use crate::style::{FlexboxContainerStyle, FlexboxItemStyle};
#[cfg(feature = "grid")]
use crate::style::{GridContainerStyle, GridItemStyle};
#[cfg(feature = "block_layout")]
use crate::BlockContainerStyle;
use core::ops::{Deref, DerefMut};

/// This trait is Taffy's abstraction for downward tree traversal.
Expand Down Expand Up @@ -251,7 +253,7 @@ pub trait LayoutGridContainer: LayoutPartialTree {
/// Extends [`LayoutPartialTree`] with getters for the styles required for CSS Block layout
pub trait LayoutBlockContainer: LayoutPartialTree {
/// The style type representing the CSS Block container's styles
type BlockContainerStyle<'a>: CoreStyle
type BlockContainerStyle<'a>: BlockContainerStyle
where
Self: 'a;
/// The style type representing each CSS Block item's styles
Expand Down
18 changes: 18 additions & 0 deletions test_fixtures/block/block_item_text_align_center.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../../scripts/gentest/test_helper.js"></script>
<link rel="stylesheet" type="text/css" href="../../scripts/gentest/test_base_style.css">
<title>
Test description
</title>
</head>
<body>

<div id="test-root" style="display: block; width: 200px; height: 200px; text-align: -webkit-center;">
<div style="max-width: 100px; height: 50px;"></div>
<div style="max-width: 300px; height: 50px;"></div>
</div>

</body>
</html>
18 changes: 18 additions & 0 deletions test_fixtures/block/block_item_text_align_left.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../../scripts/gentest/test_helper.js"></script>
<link rel="stylesheet" type="text/css" href="../../scripts/gentest/test_base_style.css">
<title>
Test description
</title>
</head>
<body>

<div id="test-root" style="display: block; width: 200px; height: 200px; text-align: -webkit-left;">
<div style="max-width: 100px; height: 50px;"></div>
<div style="max-width: 300px; height: 50px;"></div>
</div>

</body>
</html>
18 changes: 18 additions & 0 deletions test_fixtures/block/block_item_text_align_right.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../../scripts/gentest/test_helper.js"></script>
<link rel="stylesheet" type="text/css" href="../../scripts/gentest/test_base_style.css">
<title>
Test description
</title>
</head>
<body>

<div id="test-root" style="display: block; width: 200px; height: 200px; text-align: -webkit-right;">
<div style="max-width: 100px; height: 50px;"></div>
<div style="max-width: 300px; height: 50px;"></div>
</div>

</body>
</html>
Loading

0 comments on commit 42f75c6

Please sign in to comment.