Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading