From 579d6ce1f9c0ec6d42023e6a1c28e29989d33252 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 29 Dec 2022 13:31:33 -0600 Subject: [PATCH 1/3] use lightning css to parse layout attributes for taffy --- packages/native-core/Cargo.toml | 3 + packages/native-core/src/layout_attributes.rs | 871 +++++++----------- 2 files changed, 348 insertions(+), 526 deletions(-) diff --git a/packages/native-core/Cargo.toml b/packages/native-core/Cargo.toml index 309fba781..f9668fae0 100644 --- a/packages/native-core/Cargo.toml +++ b/packages/native-core/Cargo.toml @@ -24,6 +24,9 @@ parking_lot = "0.12.1" crossbeam-deque = "0.8.2" dashmap = "5.4.0" +# for parsing attributes +lightningcss = "1.0.0-alpha.38" + [dev-dependencies] rand = "0.8.5" dioxus = { path = "../dioxus", version = "^0.2.1" } \ No newline at end of file diff --git a/packages/native-core/src/layout_attributes.rs b/packages/native-core/src/layout_attributes.rs index b59177e4e..f27068324 100644 --- a/packages/native-core/src/layout_attributes.rs +++ b/packages/native-core/src/layout_attributes.rs @@ -1,7 +1,7 @@ /* - [ ] pub display: Display, - [x] pub position_type: PositionType, --> kinda, taffy doesnt support everything -- [ ] pub direction: Direction, +- [x] pub direction: Direction, - [x] pub flex_direction: FlexDirection, - [x] pub flex_wrap: FlexWrap, @@ -19,7 +19,7 @@ - [x] pub padding: Rect, - [x] pub justify_content: JustifyContent, -- [ ] pub position: Rect, +- [x] pub position: Rect, - [x] pub border: Rect, - [ ] pub size: Size, ----> ??? seems to only be relevant for input? @@ -29,6 +29,14 @@ - [ ] pub aspect_ratio: Number, */ +use lightningcss::{ + properties::{align::GapValue, border::BorderSideWidth, Property, PropertyId}, + stylesheet::ParserOptions, + values::{ + length::{Length, LengthPercentageOrAuto, LengthValue}, + percentage::DimensionPercentage, + }, +}; use taffy::{ prelude::*, style::{FlexDirection, PositionType}, @@ -36,229 +44,349 @@ use taffy::{ /// applies the entire html namespace defined in dioxus-html pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { - match name { - "align-content" - | "align-items" - | "align-self" => apply_align(name, value, style), - - "animation" - | "animation-delay" - | "animation-direction" - | "animation-duration" - | "animation-fill-mode" - | "animation-iteration-count" - | "animation-name" - | "animation-play-state" - | "animation-timing-function" => apply_animation(name, value, style), - - "backface-visibility" => {} - - "border" - | "border-bottom" - | "border-bottom-color" - | "border-bottom-left-radius" - | "border-bottom-right-radius" - | "border-bottom-style" - | "border-bottom-width" - | "border-collapse" - | "border-color" - | "border-image" - | "border-image-outset" - | "border-image-repeat" - | "border-image-slice" - | "border-image-source" - | "border-image-width" - | "border-left" - | "border-left-color" - | "border-left-style" - | "border-left-width" - | "border-radius" - | "border-right" - | "border-right-color" - | "border-right-style" - | "border-right-width" - | "border-spacing" - | "border-style" - | "border-top" - | "border-top-color" - | "border-top-left-radius" - | "border-top-right-radius" - | "border-top-style" - | "border-top-width" - | "border-width" => apply_border(name, value, style), - - "bottom" => {} - "box-shadow" => {} - "box-sizing" => {} - "caption-side" => {} - "clear" => {} - "clip" => {} - - "column-count" - | "column-fill" - | "column-gap" - | "column-rule" - | "column-rule-color" - | "column-rule-style" - | "column-rule-width" - | "column-span" - // add column-width - | "column-width" => apply_column(name, value, style), - - "columns" => {} - - "content" => {} - "counter-increment" => {} - "counter-reset" => {} - - "cursor" => {} - "direction" => {} - - "display" => apply_display(name, value, style), - - "empty-cells" => {} - - "flex" - | "flex-basis" - | "flex-direction" - | "flex-flow" - | "flex-grow" - | "flex-shrink" - | "flex-wrap" => apply_flex(name, value, style), - - "float" => {}, - - "font-style" - | "font-variant" - | "font-weight" - | "font-size" - | "line-height" - | "font-family" => apply_font(name, value, style), - - "height" => { - if let Some(v) = parse_value(value){ - style.size.height = v; + if let Ok(property) = + Property::parse_string(PropertyId::from(name), value, ParserOptions::default()) + { + match property { + Property::Display(display) => match display { + lightningcss::properties::display::Display::Keyword(_) => todo!(), + lightningcss::properties::display::Display::Pair(pair) => { + match pair.outside { + lightningcss::properties::display::DisplayOutside::Block => { + style.display = Display::None + } + lightningcss::properties::display::DisplayOutside::Inline => todo!(), + lightningcss::properties::display::DisplayOutside::RunIn => todo!(), + } + match pair.inside { + lightningcss::properties::display::DisplayInside::Flow => todo!(), + lightningcss::properties::display::DisplayInside::FlowRoot => todo!(), + lightningcss::properties::display::DisplayInside::Table => todo!(), + lightningcss::properties::display::DisplayInside::Flex(_) => { + style.display = Display::Flex + } + lightningcss::properties::display::DisplayInside::Box(_) => todo!(), + lightningcss::properties::display::DisplayInside::Grid => todo!(), + lightningcss::properties::display::DisplayInside::Ruby => todo!(), + } + } + }, + Property::Position(position) => { + style.position_type = match position { + lightningcss::properties::position::Position::Static => todo!(), + lightningcss::properties::position::Position::Relative => { + PositionType::Relative + } + lightningcss::properties::position::Position::Absolute => { + PositionType::Absolute + } + lightningcss::properties::position::Position::Sticky(_) => todo!(), + lightningcss::properties::position::Position::Fixed => todo!(), + } } - } - "justify-content" => { - use JustifyContent::*; - style.justify_content = match value { - "flex-start" => FlexStart, - "flex-end" => FlexEnd, - "center" => Center, - "space-between" => SpaceBetween, - "space-around" => SpaceAround, - "space-evenly" => SpaceEvenly, - _ => FlexStart, - }; - } - "left" => {} - "letter-spacing" => {} - - "list-style" - | "list-style-image" - | "list-style-position" - | "list-style-type" => {} - - "margin" - | "margin-bottom" - | "margin-left" - | "margin-right" - | "margin-top" => apply_margin(name, value, style), - - "max-height" => {} - "max-width" => {} - "min-height" => {} - "min-width" => {} - - "opacity" => {} - "order" => {} - "outline" => {} - - "outline-color" - | "outline-offset" - | "outline-style" - | "outline-width" => {} - - "overflow" - | "overflow-x" - | "overflow-y" => apply_overflow(name, value, style), - - "padding" - | "padding-bottom" - | "padding-left" - | "padding-right" - | "padding-top" => apply_padding(name, value, style), - - "page-break-after" - | "page-break-before" - | "page-break-inside" => {} - - "perspective" - | "perspective-origin" => {} - - "position" => { - match value { - "static" => {} - "relative" => style.position_type = PositionType::Relative, - "fixed" => {} - "absolute" => style.position_type = PositionType::Absolute, - "sticky" => {} - _ => {} + Property::Top(top) => style.position.top = convert_length_percentage_or_auto(top), + Property::Bottom(bottom) => { + style.position.bottom = convert_length_percentage_or_auto(bottom) } - - } - - "pointer-events" => {} - - "quotes" => {} - "resize" => {} - "right" => {} - "tab-size" => {} - "table-layout" => {} - - "top" => {} - - "transform" - | "transform-origin" - | "transform-style" => apply_transform(name, value, style), - - "transition" - | "transition-delay" - | "transition-duration" - | "transition-property" - | "transition-timing-function" => apply_transition(name, value, style), - - "vertical-align" => {} - "visibility" => {} - "white-space" => {} - "width" => { - if let Some(v) = parse_value(value){ - style.size.width = v; + Property::Left(left) => style.position.left = convert_length_percentage_or_auto(left), + Property::Right(right) => { + style.position.right = convert_length_percentage_or_auto(right) } + Property::BorderTopWidth(width) => { + style.border.top = convert_border_side_width(width); + } + Property::BorderBottomWidth(width) => { + style.border.bottom = convert_border_side_width(width); + } + Property::BorderLeftWidth(width) => { + style.border.left = convert_border_side_width(width); + } + Property::BorderRightWidth(width) => { + style.border.right = convert_border_side_width(width); + } + Property::BorderWidth(width) => { + style.border.top = convert_border_side_width(width.top); + style.border.bottom = convert_border_side_width(width.bottom); + style.border.left = convert_border_side_width(width.left); + style.border.right = convert_border_side_width(width.right); + } + Property::Border(border) => { + let width = convert_border_side_width(border.width); + style.border.top = width; + style.border.bottom = width; + style.border.left = width; + style.border.right = width; + } + Property::BorderTop(top) => { + style.border.top = convert_border_side_width(top.width); + } + Property::BorderBottom(bottom) => { + style.border.bottom = convert_border_side_width(bottom.width); + } + Property::BorderLeft(left) => { + style.border.left = convert_border_side_width(left.width); + } + Property::BorderRight(right) => { + style.border.right = convert_border_side_width(right.width); + } + Property::FlexDirection(flex_direction, _) => { + use FlexDirection::*; + style.flex_direction = match flex_direction { + lightningcss::properties::flex::FlexDirection::Row => Row, + lightningcss::properties::flex::FlexDirection::RowReverse => RowReverse, + lightningcss::properties::flex::FlexDirection::Column => Column, + lightningcss::properties::flex::FlexDirection::ColumnReverse => ColumnReverse, + } + } + Property::FlexWrap(wrap, _) => { + use FlexWrap::*; + style.flex_wrap = match wrap { + lightningcss::properties::flex::FlexWrap::NoWrap => NoWrap, + lightningcss::properties::flex::FlexWrap::Wrap => Wrap, + lightningcss::properties::flex::FlexWrap::WrapReverse => WrapReverse, + } + } + Property::FlexGrow(grow, _) => { + style.flex_grow = grow; + } + Property::FlexShrink(shrink, _) => { + style.flex_shrink = shrink; + } + Property::FlexBasis(basis, _) => { + style.flex_basis = convert_length_percentage_or_auto(basis); + } + Property::Flex(flex, _) => { + style.flex_grow = flex.grow; + style.flex_shrink = flex.shrink; + style.flex_basis = convert_length_percentage_or_auto(flex.basis); + } + Property::AlignContent(align, _) => { + use AlignContent::*; + style.align_content = match align { + lightningcss::properties::align::AlignContent::Normal => todo!(), + lightningcss::properties::align::AlignContent::BaselinePosition(_) => { + todo!() + } + lightningcss::properties::align::AlignContent::ContentDistribution( + distribution, + ) => match distribution { + lightningcss::properties::align::ContentDistribution::SpaceBetween => { + SpaceBetween + } + lightningcss::properties::align::ContentDistribution::SpaceAround => { + SpaceAround + } + lightningcss::properties::align::ContentDistribution::SpaceEvenly => { + SpaceEvenly + } + lightningcss::properties::align::ContentDistribution::Stretch => Stretch, + }, + lightningcss::properties::align::AlignContent::ContentPosition(_, position) => { + match position { + lightningcss::properties::align::ContentPosition::Center => Center, + lightningcss::properties::align::ContentPosition::Start => todo!(), + lightningcss::properties::align::ContentPosition::End => todo!(), + lightningcss::properties::align::ContentPosition::FlexStart => { + FlexStart + } + lightningcss::properties::align::ContentPosition::FlexEnd => FlexEnd, + } + } + }; + } + Property::JustifyContent(justify, _) => { + use JustifyContent::*; + style.justify_content = match justify { + lightningcss::properties::align::JustifyContent::Normal => todo!(), + lightningcss::properties::align::JustifyContent::ContentDistribution( + distribution, + ) => match distribution { + lightningcss::properties::align::ContentDistribution::SpaceBetween => { + SpaceBetween + } + lightningcss::properties::align::ContentDistribution::SpaceAround => { + SpaceAround + } + lightningcss::properties::align::ContentDistribution::SpaceEvenly => { + SpaceEvenly + } + lightningcss::properties::align::ContentDistribution::Stretch => todo!(), + }, + lightningcss::properties::align::JustifyContent::ContentPosition( + _, + position, + ) => match position { + lightningcss::properties::align::ContentPosition::Center => Center, + lightningcss::properties::align::ContentPosition::Start => todo!(), + lightningcss::properties::align::ContentPosition::End => todo!(), + lightningcss::properties::align::ContentPosition::FlexStart => FlexStart, + lightningcss::properties::align::ContentPosition::FlexEnd => FlexEnd, + }, + lightningcss::properties::align::JustifyContent::Left(_) => todo!(), + lightningcss::properties::align::JustifyContent::Right(_) => todo!(), + }; + } + Property::AlignSelf(align, _) => { + use AlignSelf::*; + style.align_self = match align { + lightningcss::properties::align::AlignSelf::Auto => Auto, + lightningcss::properties::align::AlignSelf::Normal => todo!(), + lightningcss::properties::align::AlignSelf::Stretch => Stretch, + lightningcss::properties::align::AlignSelf::BaselinePosition(_) => Baseline, + lightningcss::properties::align::AlignSelf::SelfPosition( + _overflow, + position, + ) => match position { + lightningcss::properties::align::SelfPosition::Center => Center, + lightningcss::properties::align::SelfPosition::Start => todo!(), + lightningcss::properties::align::SelfPosition::End => todo!(), + lightningcss::properties::align::SelfPosition::SelfStart => todo!(), + lightningcss::properties::align::SelfPosition::SelfEnd => todo!(), + lightningcss::properties::align::SelfPosition::FlexStart => FlexStart, + lightningcss::properties::align::SelfPosition::FlexEnd => FlexEnd, + }, + }; + } + Property::AlignItems(align, _) => { + use AlignItems::*; + style.align_items = match align { + lightningcss::properties::align::AlignItems::Normal => todo!(), + lightningcss::properties::align::AlignItems::BaselinePosition(_) => Baseline, + lightningcss::properties::align::AlignItems::Stretch => Stretch, + lightningcss::properties::align::AlignItems::SelfPosition( + _overflow, + position, + ) => match position { + lightningcss::properties::align::SelfPosition::Center => Center, + lightningcss::properties::align::SelfPosition::Start => todo!(), + lightningcss::properties::align::SelfPosition::End => todo!(), + lightningcss::properties::align::SelfPosition::SelfStart => todo!(), + lightningcss::properties::align::SelfPosition::SelfEnd => todo!(), + lightningcss::properties::align::SelfPosition::FlexStart => FlexStart, + lightningcss::properties::align::SelfPosition::FlexEnd => FlexEnd, + }, + }; + } + Property::RowGap(row_gap) => { + style.gap.width = convert_gap_value(row_gap); + } + Property::ColumnGap(column_gap) => { + style.gap.height = convert_gap_value(column_gap); + } + Property::Gap(gap) => { + style.gap = Size { + width: convert_gap_value(gap.row), + height: convert_gap_value(gap.column), + }; + } + Property::MarginTop(margin) => { + style.margin.top = convert_length_percentage_or_auto(margin); + } + Property::MarginBottom(margin) => { + style.margin.bottom = convert_length_percentage_or_auto(margin); + } + Property::MarginLeft(margin) => { + style.margin.left = convert_length_percentage_or_auto(margin); + } + Property::MarginRight(margin) => { + style.margin.right = convert_length_percentage_or_auto(margin); + } + Property::Margin(margin) => { + style.margin = Rect { + top: convert_length_percentage_or_auto(margin.top), + bottom: convert_length_percentage_or_auto(margin.bottom), + left: convert_length_percentage_or_auto(margin.left), + right: convert_length_percentage_or_auto(margin.right), + }; + } + Property::PaddingTop(padding) => { + style.padding.top = convert_length_percentage_or_auto(padding); + } + Property::PaddingBottom(padding) => { + style.padding.bottom = convert_length_percentage_or_auto(padding); + } + Property::PaddingLeft(padding) => { + style.padding.left = convert_length_percentage_or_auto(padding); + } + Property::PaddingRight(padding) => { + style.padding.right = convert_length_percentage_or_auto(padding); + } + Property::Padding(padding) => { + style.padding = Rect { + top: convert_length_percentage_or_auto(padding.top), + bottom: convert_length_percentage_or_auto(padding.bottom), + left: convert_length_percentage_or_auto(padding.left), + right: convert_length_percentage_or_auto(padding.right), + }; + } + Property::Width(width) => { + style.size.width = convert_size(width); + } + Property::Height(height) => { + style.size.height = convert_size(height); + } + _ => (), } - "word-break" => {} - "word-spacing" => {} - "word-wrap" => {} - "z-index" => {} - _ => {} } } -fn apply_font(name: &str, value: &str, style: &mut Style) { - match name { - "font-style" => {} - "font-variant" => {} - "font-weight" => {} - "font-size" => {} - "line-height" => { - style.size = Size { - width: style.size.width, - height: parse_value(value).unwrap_or(Dimension::Points(12.0)), - } +fn convert_length_value(length_value: LengthValue) -> Dimension { + match length_value { + LengthValue::Px(value) => Dimension::Points(value), + _ => todo!(), + } +} + +fn convert_dimention_percentage( + dimension_percentage: DimensionPercentage, +) -> Dimension { + match dimension_percentage { + DimensionPercentage::Dimension(value) => convert_length_value(value), + DimensionPercentage::Percentage(percentage) => Dimension::Percent(percentage.0), + _ => todo!(), + } +} + +fn convert_length_percentage_or_auto( + length_percentage_or_auto: LengthPercentageOrAuto, +) -> Dimension { + match length_percentage_or_auto { + LengthPercentageOrAuto::Auto => Dimension::Auto, + LengthPercentageOrAuto::LengthPercentage(percentage) => { + convert_dimention_percentage(percentage) } - "font-family" => {} - _ => {} + } +} + +fn convert_border_side_width(border_side_width: BorderSideWidth) -> Dimension { + match border_side_width { + BorderSideWidth::Length(Length::Value(value)) => convert_length_value(value), + BorderSideWidth::Thick => Dimension::Points(5.0), + BorderSideWidth::Medium => Dimension::Points(3.0), + BorderSideWidth::Thin => Dimension::Points(1.0), + _ => todo!(), + } +} + +fn convert_gap_value(gap_value: GapValue) -> Dimension { + match gap_value { + GapValue::LengthPercentage(dim) => convert_dimention_percentage(dim), + GapValue::Normal => Dimension::Auto, + } +} + +fn convert_size(size: lightningcss::properties::size::Size) -> Dimension { + match size { + lightningcss::properties::size::Size::Auto => Dimension::Auto, + lightningcss::properties::size::Size::LengthPercentage(length) => { + convert_dimention_percentage(length) + } + lightningcss::properties::size::Size::MinContent(_) => todo!(), + lightningcss::properties::size::Size::MaxContent(_) => todo!(), + lightningcss::properties::size::Size::FitContent(_) => todo!(), + lightningcss::properties::size::Size::FitContentFunction(_) => todo!(), + lightningcss::properties::size::Size::Stretch(_) => todo!(), + lightningcss::properties::size::Size::Contain => todo!(), } } @@ -280,312 +408,3 @@ pub fn parse_value(value: &str) -> Option { None } } - -fn apply_overflow(_name: &str, _value: &str, _style: &mut Style) { - // todo: add overflow support to taffy -} - -fn apply_display(_name: &str, value: &str, style: &mut Style) { - style.display = match value { - "flex" => Display::Flex, - "block" => Display::None, - _ => Display::Flex, - } - - // TODO: there are way more variants - // taffy needs to be updated to handle them - // - // "block" => Display::Block, - // "inline" => Display::Inline, - // "inline-block" => Display::InlineBlock, - // "inline-table" => Display::InlineTable, - // "list-item" => Display::ListItem, - // "run-in" => Display::RunIn, - // "table" => Display::Table, - // "table-caption" => Display::TableCaption, - // "table-cell" => Display::TableCell, - // "table-column" => Display::TableColumn, - // "table-column-group" => Display::TableColumnGroup, - // "table-footer-group" => Display::TableFooterGroup, - // "table-header-group" => Display::TableHeaderGroup, - // "table-row" => Display::TableRow, - // "table-row-group" => Display::TableRowGroup, - // "none" => Display::None, - // _ => Display::Inline, -} - -fn apply_border(name: &str, value: &str, style: &mut Style) { - match name { - "border" => {} - "border-bottom" => {} - "border-bottom-color" => {} - "border-bottom-left-radius" => {} - "border-bottom-right-radius" => {} - "border-bottom-style" => { - if style.border.bottom == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.bottom = v; - } - } - "border-bottom-width" => { - if let Some(v) = parse_value(value) { - style.border.bottom = v; - } - } - "border-collapse" => {} - "border-color" => {} - "border-image" => {} - "border-image-outset" => {} - "border-image-repeat" => {} - "border-image-slice" => {} - "border-image-source" => {} - "border-image-width" => {} - "border-left" => {} - "border-left-color" => {} - "border-left-style" => { - if style.border.left == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.left = v; - } - } - "border-left-width" => { - if let Some(v) = parse_value(value) { - style.border.left = v; - } - } - "border-radius" => {} - "border-right" => {} - "border-right-color" => {} - "border-right-style" => { - let v = Dimension::Points(1.0); - style.border.right = v; - } - "border-right-width" => { - if let Some(v) = parse_value(value) { - style.border.right = v; - } - } - "border-spacing" => {} - "border-style" => { - if style.border.top == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.top = v; - } - if style.border.bottom == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.bottom = v; - } - if style.border.left == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.left = v; - } - if style.border.right == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.right = v; - } - } - "border-top" => {} - "border-top-color" => {} - "border-top-left-radius" => {} - "border-top-right-radius" => {} - "border-top-style" => { - if style.border.top == Dimension::default() { - let v = Dimension::Points(1.0); - style.border.top = v; - } - } - "border-top-width" => { - if let Some(v) = parse_value(value) { - style.border.top = v; - } - } - "border-width" => { - let values: Vec<_> = value.split(' ').collect(); - if values.len() == 1 { - if let Some(dim) = parse_value(values[0]) { - style.border = Rect { - right: dim, - left: dim, - top: dim, - bottom: dim, - }; - } - } else { - let border_widths = [ - &mut style.border.top, - &mut style.border.bottom, - &mut style.border.left, - &mut style.border.right, - ]; - for (v, width) in values.into_iter().zip(border_widths) { - if let Some(w) = parse_value(v) { - *width = w; - } - } - } - } - _ => (), - } -} - -fn apply_animation(name: &str, _value: &str, _style: &mut Style) { - match name { - "animation" => {} - "animation-delay" => {} - "animation-direction =>{}" => {} - "animation-duration" => {} - "animation-fill-mode" => {} - "animation-itera =>{}tion-count" => {} - "animation-name" => {} - "animation-play-state" => {} - "animation-timing-function" => {} - _ => {} - } -} - -fn apply_column(name: &str, _value: &str, _style: &mut Style) { - match name { - "column-count" => {} - "column-fill" => {} - "column-gap" => {} - "column-rule" => {} - "column-rule-color" => {} - "column-rule-style" => {} - "column-rule-width" => {} - "column-span" => {} - "column-width" => {} - _ => {} - } -} - -fn apply_flex(name: &str, value: &str, style: &mut Style) { - // - [x] pub flex_direction: FlexDirection, - // - [x] pub flex_wrap: FlexWrap, - // - [x] pub flex_grow: f32, - // - [x] pub flex_shrink: f32, - // - [x] pub flex_basis: Dimension, - - match name { - "flex" => {} - "flex-direction" => { - use FlexDirection::*; - style.flex_direction = match value { - "row" => Row, - "row-reverse" => RowReverse, - "column" => Column, - "column-reverse" => ColumnReverse, - _ => Row, - }; - } - "flex-basis" => { - if let Some(v) = parse_value(value) { - style.flex_basis = v; - } - } - "flex-flow" => {} - "flex-grow" => { - if let Ok(val) = value.parse::() { - style.flex_grow = val; - } - } - "flex-shrink" => { - if let Ok(px) = value.parse::() { - style.flex_shrink = px; - } - } - "flex-wrap" => { - use FlexWrap::*; - style.flex_wrap = match value { - "nowrap" => NoWrap, - "wrap" => Wrap, - "wrap-reverse" => WrapReverse, - _ => NoWrap, - }; - } - _ => {} - } -} - -fn apply_padding(name: &str, value: &str, style: &mut Style) { - if let Some(v) = parse_value(value) { - match name { - "padding" => { - style.padding.top = v; - style.padding.bottom = v; - style.padding.left = v; - style.padding.right = v; - } - "padding-bottom" => style.padding.bottom = v, - "padding-left" => style.padding.left = v, - "padding-right" => style.padding.right = v, - "padding-top" => style.padding.top = v, - _ => {} - } - } -} - -fn apply_transform(_name: &str, _value: &str, _style: &mut Style) { - todo!() -} - -fn apply_transition(_name: &str, _value: &str, _style: &mut Style) { - todo!() -} - -fn apply_align(name: &str, value: &str, style: &mut Style) { - match name { - "align-items" => { - use AlignItems::*; - style.align_items = match value { - "flex-start" => FlexStart, - "flex-end" => FlexEnd, - "center" => Center, - "baseline" => Baseline, - "stretch" => Stretch, - _ => FlexStart, - }; - } - "align-content" => { - use AlignContent::*; - style.align_content = match value { - "flex-start" => FlexStart, - "flex-end" => FlexEnd, - "center" => Center, - "space-between" => SpaceBetween, - "space-around" => SpaceAround, - _ => FlexStart, - }; - } - "align-self" => { - use AlignSelf::*; - style.align_self = match value { - "auto" => Auto, - "flex-start" => FlexStart, - "flex-end" => FlexEnd, - "center" => Center, - "baseline" => Baseline, - "stretch" => Stretch, - _ => Auto, - }; - } - _ => {} - } -} - -fn apply_margin(name: &str, value: &str, style: &mut Style) { - if let Some(dim) = parse_value(value) { - match name { - "margin" => { - style.margin.top = dim; - style.margin.bottom = dim; - style.margin.left = dim; - style.margin.right = dim; - } - "margin-top" => style.margin.top = dim, - "margin-bottom" => style.margin.bottom = dim, - "margin-left" => style.margin.left = dim, - "margin-right" => style.margin.right = dim, - _ => {} - } - } -} From f6fb6e1d1b784c7b61e74ba0e1c349c7b37edb8d Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 29 Dec 2022 14:14:29 -0600 Subject: [PATCH 2/3] add aspect ratio parsing --- packages/native-core/src/layout_attributes.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/native-core/src/layout_attributes.rs b/packages/native-core/src/layout_attributes.rs index f27068324..de5acbe5b 100644 --- a/packages/native-core/src/layout_attributes.rs +++ b/packages/native-core/src/layout_attributes.rs @@ -1,6 +1,6 @@ /* -- [ ] pub display: Display, -- [x] pub position_type: PositionType, --> kinda, taffy doesnt support everything +- [ ] pub display: Display, ----> taffy doesnt support all display types +- [x] pub position_type: PositionType, --> taffy doesnt support everything - [x] pub direction: Direction, - [x] pub flex_direction: FlexDirection, @@ -9,7 +9,7 @@ - [x] pub flex_shrink: f32, - [x] pub flex_basis: Dimension, -- [x] pub overflow: Overflow, ---> kinda implemented... taffy doesnt have support for directional overflow +- [x] pub overflow: Overflow, ---> taffy doesnt have support for directional overflow - [x] pub align_items: AlignItems, - [x] pub align_self: AlignSelf, @@ -22,19 +22,21 @@ - [x] pub position: Rect, - [x] pub border: Rect, -- [ ] pub size: Size, ----> ??? seems to only be relevant for input? +- [ ] pub size: Size, ----> seems to only be relevant for input? - [ ] pub min_size: Size, - [ ] pub max_size: Size, -- [ ] pub aspect_ratio: Number, +- [ ] pub aspect_ratio: Number, ----> parsing is done, but taffy doesnt support it */ use lightningcss::{ properties::{align::GapValue, border::BorderSideWidth, Property, PropertyId}, stylesheet::ParserOptions, + traits::Parse, values::{ length::{Length, LengthPercentageOrAuto, LengthValue}, percentage::DimensionPercentage, + ratio::Ratio, }, }; use taffy::{ @@ -327,6 +329,12 @@ pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { } _ => (), } + // currently not implemented in lightningcss + if name == "aspect-ratio" { + if let Ok(ratio) = Ratio::parse_string(value) { + style.aspect_ratio = Some(ratio.0 / ratio.1); + } + } } } From 2da1d8ab27270d3cf703c7135aa1e09152af971d Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 29 Dec 2022 21:34:17 -0600 Subject: [PATCH 3/3] clean up implementation --- packages/native-core/src/layout_attributes.rs | 207 +++++++----------- 1 file changed, 78 insertions(+), 129 deletions(-) diff --git a/packages/native-core/src/layout_attributes.rs b/packages/native-core/src/layout_attributes.rs index de5acbe5b..7d722d5de 100644 --- a/packages/native-core/src/layout_attributes.rs +++ b/packages/native-core/src/layout_attributes.rs @@ -29,6 +29,7 @@ - [ ] pub aspect_ratio: Number, ----> parsing is done, but taffy doesnt support it */ +use lightningcss::properties::{align, display, flex, position, size}; use lightningcss::{ properties::{align::GapValue, border::BorderSideWidth, Property, PropertyId}, stylesheet::ParserOptions, @@ -51,39 +52,21 @@ pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { { match property { Property::Display(display) => match display { - lightningcss::properties::display::Display::Keyword(_) => todo!(), - lightningcss::properties::display::Display::Pair(pair) => { - match pair.outside { - lightningcss::properties::display::DisplayOutside::Block => { - style.display = Display::None - } - lightningcss::properties::display::DisplayOutside::Inline => todo!(), - lightningcss::properties::display::DisplayOutside::RunIn => todo!(), - } - match pair.inside { - lightningcss::properties::display::DisplayInside::Flow => todo!(), - lightningcss::properties::display::DisplayInside::FlowRoot => todo!(), - lightningcss::properties::display::DisplayInside::Table => todo!(), - lightningcss::properties::display::DisplayInside::Flex(_) => { - style.display = Display::Flex - } - lightningcss::properties::display::DisplayInside::Box(_) => todo!(), - lightningcss::properties::display::DisplayInside::Grid => todo!(), - lightningcss::properties::display::DisplayInside::Ruby => todo!(), + display::Display::Keyword(display::DisplayKeyword::None) => { + style.display = Display::None + } + display::Display::Pair(pair) => { + if let display::DisplayInside::Flex(_) = pair.inside { + style.display = Display::Flex } } + _ => (), }, Property::Position(position) => { style.position_type = match position { - lightningcss::properties::position::Position::Static => todo!(), - lightningcss::properties::position::Position::Relative => { - PositionType::Relative - } - lightningcss::properties::position::Position::Absolute => { - PositionType::Absolute - } - lightningcss::properties::position::Position::Sticky(_) => todo!(), - lightningcss::properties::position::Position::Fixed => todo!(), + position::Position::Relative => PositionType::Relative, + position::Position::Absolute => PositionType::Absolute, + _ => return, } } Property::Top(top) => style.position.top = convert_length_percentage_or_auto(top), @@ -94,6 +77,12 @@ pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { Property::Right(right) => { style.position.right = convert_length_percentage_or_auto(right) } + Property::Inset(inset) => { + style.position.top = convert_length_percentage_or_auto(inset.top); + style.position.bottom = convert_length_percentage_or_auto(inset.bottom); + style.position.left = convert_length_percentage_or_auto(inset.left); + style.position.right = convert_length_percentage_or_auto(inset.right); + } Property::BorderTopWidth(width) => { style.border.top = convert_border_side_width(width); } @@ -134,18 +123,18 @@ pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { Property::FlexDirection(flex_direction, _) => { use FlexDirection::*; style.flex_direction = match flex_direction { - lightningcss::properties::flex::FlexDirection::Row => Row, - lightningcss::properties::flex::FlexDirection::RowReverse => RowReverse, - lightningcss::properties::flex::FlexDirection::Column => Column, - lightningcss::properties::flex::FlexDirection::ColumnReverse => ColumnReverse, + flex::FlexDirection::Row => Row, + flex::FlexDirection::RowReverse => RowReverse, + flex::FlexDirection::Column => Column, + flex::FlexDirection::ColumnReverse => ColumnReverse, } } Property::FlexWrap(wrap, _) => { use FlexWrap::*; style.flex_wrap = match wrap { - lightningcss::properties::flex::FlexWrap::NoWrap => NoWrap, - lightningcss::properties::flex::FlexWrap::Wrap => Wrap, - lightningcss::properties::flex::FlexWrap::WrapReverse => WrapReverse, + flex::FlexWrap::NoWrap => NoWrap, + flex::FlexWrap::Wrap => Wrap, + flex::FlexWrap::WrapReverse => WrapReverse, } } Property::FlexGrow(grow, _) => { @@ -165,108 +154,75 @@ pub fn apply_layout_attributes(name: &str, value: &str, style: &mut Style) { Property::AlignContent(align, _) => { use AlignContent::*; style.align_content = match align { - lightningcss::properties::align::AlignContent::Normal => todo!(), - lightningcss::properties::align::AlignContent::BaselinePosition(_) => { - todo!() - } - lightningcss::properties::align::AlignContent::ContentDistribution( - distribution, - ) => match distribution { - lightningcss::properties::align::ContentDistribution::SpaceBetween => { - SpaceBetween - } - lightningcss::properties::align::ContentDistribution::SpaceAround => { - SpaceAround - } - lightningcss::properties::align::ContentDistribution::SpaceEvenly => { - SpaceEvenly - } - lightningcss::properties::align::ContentDistribution::Stretch => Stretch, + align::AlignContent::ContentDistribution(distribution) => match distribution { + align::ContentDistribution::SpaceBetween => SpaceBetween, + align::ContentDistribution::SpaceAround => SpaceAround, + align::ContentDistribution::SpaceEvenly => SpaceEvenly, + align::ContentDistribution::Stretch => Stretch, }, - lightningcss::properties::align::AlignContent::ContentPosition(_, position) => { - match position { - lightningcss::properties::align::ContentPosition::Center => Center, - lightningcss::properties::align::ContentPosition::Start => todo!(), - lightningcss::properties::align::ContentPosition::End => todo!(), - lightningcss::properties::align::ContentPosition::FlexStart => { - FlexStart - } - lightningcss::properties::align::ContentPosition::FlexEnd => FlexEnd, + align::AlignContent::ContentPosition(_, position) => match position { + align::ContentPosition::Center => Center, + align::ContentPosition::Start | align::ContentPosition::FlexStart => { + FlexStart } - } + align::ContentPosition::End | align::ContentPosition::FlexEnd => FlexEnd, + }, + _ => return, }; } Property::JustifyContent(justify, _) => { use JustifyContent::*; style.justify_content = match justify { - lightningcss::properties::align::JustifyContent::Normal => todo!(), - lightningcss::properties::align::JustifyContent::ContentDistribution( - distribution, - ) => match distribution { - lightningcss::properties::align::ContentDistribution::SpaceBetween => { - SpaceBetween + align::JustifyContent::ContentDistribution(distribution) => { + match distribution { + align::ContentDistribution::SpaceBetween => SpaceBetween, + align::ContentDistribution::SpaceAround => SpaceAround, + align::ContentDistribution::SpaceEvenly => SpaceEvenly, + _ => return, } - lightningcss::properties::align::ContentDistribution::SpaceAround => { - SpaceAround + } + align::JustifyContent::ContentPosition(_, position) => match position { + align::ContentPosition::Center => Center, + // start ignores -reverse flex-direction but there is no way to specify that in Taffy + align::ContentPosition::Start | align::ContentPosition::FlexStart => { + FlexStart } - lightningcss::properties::align::ContentDistribution::SpaceEvenly => { - SpaceEvenly - } - lightningcss::properties::align::ContentDistribution::Stretch => todo!(), + // end ignores -reverse flex-direction but there is no way to specify that in Taffy + align::ContentPosition::End | align::ContentPosition::FlexEnd => FlexEnd, }, - lightningcss::properties::align::JustifyContent::ContentPosition( - _, - position, - ) => match position { - lightningcss::properties::align::ContentPosition::Center => Center, - lightningcss::properties::align::ContentPosition::Start => todo!(), - lightningcss::properties::align::ContentPosition::End => todo!(), - lightningcss::properties::align::ContentPosition::FlexStart => FlexStart, - lightningcss::properties::align::ContentPosition::FlexEnd => FlexEnd, - }, - lightningcss::properties::align::JustifyContent::Left(_) => todo!(), - lightningcss::properties::align::JustifyContent::Right(_) => todo!(), + _ => return, }; } Property::AlignSelf(align, _) => { use AlignSelf::*; style.align_self = match align { - lightningcss::properties::align::AlignSelf::Auto => Auto, - lightningcss::properties::align::AlignSelf::Normal => todo!(), - lightningcss::properties::align::AlignSelf::Stretch => Stretch, - lightningcss::properties::align::AlignSelf::BaselinePosition(_) => Baseline, - lightningcss::properties::align::AlignSelf::SelfPosition( - _overflow, - position, - ) => match position { - lightningcss::properties::align::SelfPosition::Center => Center, - lightningcss::properties::align::SelfPosition::Start => todo!(), - lightningcss::properties::align::SelfPosition::End => todo!(), - lightningcss::properties::align::SelfPosition::SelfStart => todo!(), - lightningcss::properties::align::SelfPosition::SelfEnd => todo!(), - lightningcss::properties::align::SelfPosition::FlexStart => FlexStart, - lightningcss::properties::align::SelfPosition::FlexEnd => FlexEnd, + align::AlignSelf::Auto => Auto, + align::AlignSelf::Stretch => Stretch, + align::AlignSelf::BaselinePosition(_) => Baseline, + align::AlignSelf::SelfPosition(_overflow, position) => match position { + align::SelfPosition::Center => Center, + align::SelfPosition::Start + | align::SelfPosition::SelfStart + | align::SelfPosition::FlexStart => FlexStart, + align::SelfPosition::End + | align::SelfPosition::SelfEnd + | align::SelfPosition::FlexEnd => FlexEnd, }, + _ => return, }; } Property::AlignItems(align, _) => { use AlignItems::*; style.align_items = match align { - lightningcss::properties::align::AlignItems::Normal => todo!(), - lightningcss::properties::align::AlignItems::BaselinePosition(_) => Baseline, - lightningcss::properties::align::AlignItems::Stretch => Stretch, - lightningcss::properties::align::AlignItems::SelfPosition( - _overflow, - position, - ) => match position { - lightningcss::properties::align::SelfPosition::Center => Center, - lightningcss::properties::align::SelfPosition::Start => todo!(), - lightningcss::properties::align::SelfPosition::End => todo!(), - lightningcss::properties::align::SelfPosition::SelfStart => todo!(), - lightningcss::properties::align::SelfPosition::SelfEnd => todo!(), - lightningcss::properties::align::SelfPosition::FlexStart => FlexStart, - lightningcss::properties::align::SelfPosition::FlexEnd => FlexEnd, + align::AlignItems::BaselinePosition(_) => Baseline, + align::AlignItems::Stretch => Stretch, + align::AlignItems::SelfPosition(_overflow, position) => match position { + align::SelfPosition::Center => Center, + align::SelfPosition::FlexStart => FlexStart, + align::SelfPosition::FlexEnd => FlexEnd, + _ => return, }, + _ => return, }; } Property::RowGap(row_gap) => { @@ -345,7 +301,7 @@ fn convert_length_value(length_value: LengthValue) -> Dimension { } } -fn convert_dimention_percentage( +fn convert_dimension_percentage( dimension_percentage: DimensionPercentage, ) -> Dimension { match dimension_percentage { @@ -361,7 +317,7 @@ fn convert_length_percentage_or_auto( match length_percentage_or_auto { LengthPercentageOrAuto::Auto => Dimension::Auto, LengthPercentageOrAuto::LengthPercentage(percentage) => { - convert_dimention_percentage(percentage) + convert_dimension_percentage(percentage) } } } @@ -378,23 +334,16 @@ fn convert_border_side_width(border_side_width: BorderSideWidth) -> Dimension { fn convert_gap_value(gap_value: GapValue) -> Dimension { match gap_value { - GapValue::LengthPercentage(dim) => convert_dimention_percentage(dim), + GapValue::LengthPercentage(dim) => convert_dimension_percentage(dim), GapValue::Normal => Dimension::Auto, } } -fn convert_size(size: lightningcss::properties::size::Size) -> Dimension { +fn convert_size(size: size::Size) -> Dimension { match size { - lightningcss::properties::size::Size::Auto => Dimension::Auto, - lightningcss::properties::size::Size::LengthPercentage(length) => { - convert_dimention_percentage(length) - } - lightningcss::properties::size::Size::MinContent(_) => todo!(), - lightningcss::properties::size::Size::MaxContent(_) => todo!(), - lightningcss::properties::size::Size::FitContent(_) => todo!(), - lightningcss::properties::size::Size::FitContentFunction(_) => todo!(), - lightningcss::properties::size::Size::Stretch(_) => todo!(), - lightningcss::properties::size::Size::Contain => todo!(), + size::Size::Auto => Dimension::Auto, + size::Size::LengthPercentage(length) => convert_dimension_percentage(length), + _ => todo!(), } }