Skip to content

Commit

Permalink
Merge pull request #2 from wechat-miniprogram/feat-gap
Browse files Browse the repository at this point in the history
feat: impl the gap property
  • Loading branch information
LastLeaf authored Dec 5, 2024
2 parents d9c03a4 + 80edb85 commit 24a66e2
Show file tree
Hide file tree
Showing 13 changed files with 456 additions and 107 deletions.
16 changes: 16 additions & 0 deletions float-pigment-css/src/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ property_list! (PropertyValueWithGlobal, {
0x28 FlexBasis: LengthType as Initial default Length::Undefined, resolver = Length::resolve_em;
0x29 JustifyItems: JustifyItemsType as Initial default JustifyItems::Stretch;
0x2a Order: NumberType as Initial default Number::I32(0);
0x2b RowGap: GapType as Initial default Gap::Normal;
0x2c ColumnGap: GapType as Initial default Gap::Normal;

// background
0x30 BackgroundColor: ColorType as Initial default Color::Undefined;
Expand Down Expand Up @@ -330,6 +332,20 @@ property_value_format! (PropertyValueWithGlobal, {
| "right" => JustifyItems::Right
}};
order: {{ Order = <number> -> |x: Number| Number::I32(x.to_i32()); }};
<gap_repr: Gap>:
"normal" => Gap::Normal
| <non_negative_length> -> |length| Gap::Length(length);
;
column_gap: {{ ColumnGap = <gap_repr> }};
row_gap: {{ RowGap = <gap_repr> }};
gap: {{ (RowGap, ColumnGap)
= [ <gap_repr> <gap_repr>? ] -> |(row_gap, column_gap): (Gap, Option<Gap>)| {
if let Some(column_gap) = column_gap {
return (row_gap, column_gap);
}
return (row_gap.clone(), row_gap);
};
}};
flex_grow: {{ FlexGrow = <number> }};
flex_shrink: {{ FlexShrink = <number> }};
flex_basis: {{ FlexBasis = <length> }};
Expand Down
11 changes: 11 additions & 0 deletions float-pigment-css/src/typing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1785,3 +1785,14 @@ pub struct FeatureTag {
/// The optional number value in `font-feature-settings`.
pub value: Number,
}

#[allow(missing_docs)]
#[repr(C)]
#[property_value_type(PropertyValueWithGlobal for GapType)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ResolveFontSize)]
#[cfg_attr(debug_assertions, derive(CompatibilityEnumCheck))]
pub enum Gap {
Normal,
#[resolve_font_size(Length::resolve_em_and_ratio)]
Length(Length),
}
9 changes: 9 additions & 0 deletions float-pigment-css/src/typing_stringify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2327,3 +2327,12 @@ impl fmt::Display for FontFeatureSettings {
write!(f, "{}", ret.join(","))
}
}

impl fmt::Display for Gap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Gap::Normal => write!(f, "normal"),
Gap::Length(length) => write!(f, "{}", length),
}
}
}
36 changes: 36 additions & 0 deletions float-pigment-css/tests/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,42 @@ mod flex {
test_parse_property!(order, "order", "1", Number::I32(1));
test_parse_property!(order, "order", "-100", Number::I32(-100));
}
// 0x2b
#[test]
fn row_gap() {
test_parse_property!(row_gap, "row-gap", "normal", Gap::Normal);
test_parse_property!(row_gap, "row-gap", "10px", Gap::Length(Length::Px(10.)));
}

// 0x2c
#[test]
fn column_gap() {
test_parse_property!(column_gap, "column-gap", "normal", Gap::Normal);
test_parse_property!(column_gap, "column-gap", "-10%", Gap::Normal);
}

#[test]
fn gap() {
test_parse_property!(row_gap, "gap", "normal", Gap::Normal);
test_parse_property!(column_gap, "gap", "normal", Gap::Normal);

test_parse_property!(row_gap, "gap", "30px", Gap::Length(Length::Px(30.)));
test_parse_property!(column_gap, "gap", "20px", Gap::Length(Length::Px(20.)));

test_parse_property!(row_gap, "gap", "normal 10px", Gap::Normal);
test_parse_property!(row_gap, "gap", "10px normal", Gap::Length(Length::Px(10.)));
test_parse_property!(
column_gap,
"gap",
"normal 10px",
Gap::Length(Length::Px(10.))
);
test_parse_property!(column_gap, "gap", "10px normal", Gap::Normal);

test_parse_property!(row_gap, "gap", "30px 40px", Gap::Length(Length::Px(30.)));
test_parse_property!(column_gap, "gap", "30px 40px", Gap::Length(Length::Px(40.)));
}

#[test]
fn flex_flow() {
let mut ssg = StyleSheetGroup::new();
Expand Down
65 changes: 65 additions & 0 deletions float-pigment-forest/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,71 @@ pub unsafe extern "C" fn NodeStyleSetOrder(node: NodePtr, value: i32) {
node.set_order(value);
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetRowGap(node: NodePtr, value: f32) {
let node = &*(node.ptr as *mut Node);
node.set_row_gap(DefLength::Points(Len::from_f32(value)));
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetRowGapNormal(node: NodePtr) {
let node = &*(node.ptr as *mut Node);
node.set_row_gap(DefLength::Undefined);
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetRowGapPercentage(node: NodePtr, value: f32) {
let node = &*(node.ptr as *mut Node);
node.set_row_gap(DefLength::Percent(value));
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetRowGapCalcHandle(node: NodePtr, calc_handle: i32) {
let node = &*(node.ptr as *mut Node);
node.set_row_gap(DefLength::Custom(calc_handle));
}

/// # Safety
///
#[no_mangle]

pub unsafe extern "C" fn NodeStyleSetColumnGap(node: NodePtr, value: f32) {
let node = &*(node.ptr as *mut Node);
node.set_column_gap(DefLength::Points(Len::from_f32(value)));
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetColumnGapNormal(node: NodePtr) {
let node = &*(node.ptr as *mut Node);
node.set_column_gap(DefLength::Undefined);
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetColumnGapPercentage(node: NodePtr, value: f32) {
let node = &*(node.ptr as *mut Node);
node.set_column_gap(DefLength::Percent(value));
}

/// # Safety
///
#[no_mangle]
pub unsafe extern "C" fn NodeStyleSetColumnGapCalcHandle(node: NodePtr, calc_handle: i32) {
let node = &*(node.ptr as *mut Node);
node.set_column_gap(DefLength::Custom(calc_handle));
}

/// # Safety
///
#[no_mangle]
Expand Down
10 changes: 10 additions & 0 deletions float-pigment-forest/src/layout/layout_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,4 +685,14 @@ impl LayoutStyle<Len> for Node {
fn text_align(&self) -> TextAlign {
self.style_manager().text_align()
}

#[inline]
fn row_gap(&self) -> Length {
self.style_manager().row_gap()
}

#[inline]
fn column_gap(&self) -> Length {
self.style_manager().column_gap()
}
}
12 changes: 12 additions & 0 deletions float-pigment-forest/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,8 @@ pub trait StyleSetter {
unsafe fn set_aspect_ratio(&self, value: Option<f32>);
unsafe fn set_order(&self, value: i32);
unsafe fn set_text_align(&self, value: TextAlign);
unsafe fn set_row_gap(&self, value: Length);
unsafe fn set_column_gap(&self, value: Length);
}

impl StyleSetter for Node {
Expand Down Expand Up @@ -857,6 +859,16 @@ impl StyleSetter for Node {
self.mark_dirty_propagate();
}
}
unsafe fn set_row_gap(&self, value: Length) {
if self.style_manager_mut().set_row_gap(value) {
self.mark_dirty_propagate();
}
}
unsafe fn set_column_gap(&self, value: Length) {
if self.style_manager_mut().set_column_gap(value) {
self.mark_dirty_propagate();
}
}
}

#[cfg(test)]
Expand Down
30 changes: 30 additions & 0 deletions float-pigment-forest/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ struct OtherStyle {
pub overflow_y: Overflow,
pub text_align: TextAlign,
pub aspect_ratio: Option<f32>,
pub row_gap: Length,
pub column_gap: Length,
}

impl Default for OtherStyle {
Expand All @@ -87,6 +89,8 @@ impl Default for OtherStyle {
overflow_y: Overflow::Visible,
text_align: TextAlign::Start,
aspect_ratio: None,
row_gap: Length::Undefined,
column_gap: Length::Undefined,
}
}
}
Expand Down Expand Up @@ -945,4 +949,30 @@ impl StyleManager {
self.flex_style().flex_basis = value;
true
}

pub(crate) fn row_gap(&self) -> Length {
self.other_style().row_gap.clone()
}

pub(crate) fn set_row_gap(&self, value: Length) -> bool {
if self.other_style().row_gap == value {
return false;
}
self.clone_style(StyleBit::Other);
self.other_style().row_gap = value;
true
}

pub(crate) fn column_gap(&self) -> Length {
self.other_style().column_gap.clone()
}

pub(crate) fn set_column_gap(&self, value: Length) -> bool {
if self.other_style().column_gap == value {
return false;
}
self.clone_style(StyleBit::Other);
self.other_style().column_gap = value;
true
}
}
61 changes: 61 additions & 0 deletions float-pigment-forest/tests/custom/css_flexbox/gap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use crate::*;

#[test]
fn gap() {
assert_xml!(
r#"
<div style="display: flex; width: 100px; gap: 10px;">
<div style="height: 10px; flex: 1" expect_width="45"></div>
<div style="height: 10px; flex: 1" expect_width="45" expect_left="55"></div>
</div>
"#
)
}

#[test]
fn column_gap_in_flex_row_box() {
assert_xml!(
r#"
<div style="display: flex; width: 100px; column-gap: 10px; flex-wrap: wrap;">
<div style="width: 100px; height: 30px; flex-shrink: 0" expect_width="100"></div>
<div style="width: 100px; height: 30px; flex-shrink: 0" expect_width="100" expect_top="40"></div>
</div>
"#
)
}

#[test]
fn row_gap_in_flex_row_box() {
assert_xml!(
r#"
<div style="display: flex; width: 100px; row-gap: 10px;">
<div style="height: 10px; flex: 1" expect_width="45"></div>
<div style="height: 10px; flex: 1" expect_width="45" expect_left="55"></div>
</div>
"#
)
}

#[test]
fn column_gap_in_flex_column_box() {
assert_xml!(
r#"
<div style="display: flex; flex-direction: column; width: 100px; height: 50px; column-gap: 10px; flex-wrap: wrap; align-content: flex-start">
<div style="width: 30px; height: 30px; flex-shrink: 0" expect_height="30"></div>
<div style="width: 30px; height: 30px; flex-shrink: 0" expect_height="30" expect_left="40"></div>
</div>
"#
)
}

#[test]
fn row_gap_in_flex_column_box() {
assert_xml!(
r#"
<div style="display: flex; flex-direction: column; width: 100px; height: 100px; row-gap: 10px;">
<div style="width: 100px; height: 30px;" expect_width="100"></div>
<div style="width: 100px; height: 30px;" expect_width="100" expect_top="40"></div>
</div>
"#
)
}
1 change: 1 addition & 0 deletions float-pigment-forest/tests/custom/css_flexbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ mod order;
mod align_content;

mod flex_item_margin;
mod gap;
32 changes: 31 additions & 1 deletion float-pigment-forest/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub use float_pigment_css::length_num::LengthNum;
use float_pigment_css::{
parser::parse_inline_style,
property::NodeProperties,
typing::{AspectRatio, Display},
typing::{AspectRatio, Display, Gap},
};
pub use float_pigment_forest::Len;
use float_pigment_forest::{layout::LayoutPosition, node::Length, *};
Expand Down Expand Up @@ -389,6 +389,36 @@ impl TestCtx {
},
"order" => node.set_order(node_props.order().to_i32()),
"text-align" => node.set_text_align(node_props.text_align()),
"gap" => {
node.set_row_gap({
match node_props.row_gap() {
Gap::Length(l) => def_length(l),
Gap::Normal => Length::Undefined,
}
});
node.set_column_gap({
match node_props.column_gap() {
Gap::Length(l) => def_length(l),
Gap::Normal => Length::Undefined,
}
});
}
"column-gap" => {
node.set_column_gap({
match node_props.column_gap() {
Gap::Length(l) => def_length(l),
Gap::Normal => Length::Undefined,
}
});
}
"row-gap" => {
node.set_row_gap({
match node_props.row_gap() {
Gap::Length(l) => def_length(l),
Gap::Normal => Length::Undefined,
}
});
}
_ => {}
}
});
Expand Down
Loading

0 comments on commit 24a66e2

Please sign in to comment.