Skip to main content

float_pigment_forest/layout/
layout_impl.rs

1use float_pigment_css::length_num::*;
2use float_pigment_css::typing::{GridAutoFlow, JustifyItems, JustifySelf, TextAlign};
3use float_pigment_css::{
4    num_traits::Zero,
5    typing::{
6        AlignContent, AlignItems, AlignSelf, BoxSizing, Direction, Display, FlexDirection,
7        FlexWrap, JustifyContent, Position, WritingMode,
8    },
9};
10use float_pigment_layout::{
11    DefLength, EdgeOption, InlineMeasure, InlineUnit, InlineUnitMetadata, LayoutNode, LayoutStyle,
12    LayoutTreeNode, LayoutTreeVisitor, MeasureResult, OptionNum, OptionSize, Point, Size,
13    SizingMode, Vector,
14};
15
16use crate::{convert_node_ref_to_ptr, LayoutGridAuto, LayoutGridTemplate, Length};
17use crate::{
18    env::Env,
19    node::{ChildOperation, Node},
20    Len, MeasureMode, NodeType,
21};
22
23fn is_specified(x: Len) -> bool {
24    x != Len::MAX
25}
26
27impl LayoutTreeNode for Node {
28    type Length = Len;
29    type LengthCustom = i32;
30    type TreeVisitor = Node;
31    type Style = Node;
32    type InlineUnit = LayoutInlineUnit;
33    type InlineMeasure = LayoutInlineMeasure;
34    type Env = Env;
35
36    #[inline]
37    fn layout_node(&self) -> &LayoutNode<Self> {
38        &self.layout_node
39    }
40
41    #[inline]
42    fn tree_visitor(&self) -> &Self::TreeVisitor {
43        self
44    }
45
46    #[inline]
47    fn style(&self) -> &Self::Style {
48        self
49    }
50
51    #[inline]
52    fn resolve_custom_length(
53        &self,
54        custom: &Self::LengthCustom,
55        owner: Self::Length,
56    ) -> Self::Length {
57        if let Some(func) = self.resolve_calc() {
58            return func(*custom, owner);
59        };
60        Len::zero()
61    }
62
63    #[inline]
64    fn should_measure(&self, _env: &mut Self::Env) -> bool {
65        self.has_measure_func()
66    }
67
68    #[inline]
69    fn measure_block_size(
70        &self,
71        _env: &mut Self::Env,
72        req_size: OptionSize<Self::Length>,
73        min: Size<Self::Length>,
74        max: Size<Self::Length>,
75        max_content: OptionSize<Self::Length>,
76        _update_position: bool,
77        _sizing_mode: SizingMode,
78    ) -> MeasureResult<Self::Length> {
79        let width = req_size.width.val();
80        let height = req_size.height.val();
81        let mut size = Size::new(Len::zero(), Len::zero());
82        let mut skip_measure = false;
83        if let (Some(width), Some(height)) = (width, height) {
84            if self.style().width() != DefLength::Auto
85                && self.style().height() != DefLength::Auto
86                && is_specified(width)
87                && is_specified(height)
88            {
89                size = Size::new(width, height);
90                skip_measure = true
91            }
92        } else if let Some(ratio) = self.style().aspect_ratio() {
93            if let Some(height) = height {
94                if is_specified(height) {
95                    size = Size::new(height.mul_f32(ratio), height);
96                    skip_measure = true;
97                }
98            } else if let Some(width) = width {
99                if is_specified(width) {
100                    size = Size::new(width, width.div_f32(ratio));
101                    skip_measure = true;
102                }
103            }
104        }
105        if !skip_measure {
106            if let Some(func) = unsafe { self.measure_func() } {
107                let mut width_measure_mode = MeasureMode::AtMost;
108                let mut height_measure_mode = MeasureMode::AtMost;
109                let (min_width, max_width) = if let Some(req_size_width) = req_size.width.val() {
110                    let min_width = req_size_width;
111                    let max_width = req_size_width;
112                    width_measure_mode = MeasureMode::Exactly;
113                    (min_width, max_width)
114                } else {
115                    let min_width = if !is_specified(min.width) {
116                        Len::zero()
117                    } else {
118                        min.width
119                    };
120                    let max_width = max.width;
121                    (min_width, max_width)
122                };
123                let (min_height, max_height) = if let Some(req_size_height) = req_size.height.val()
124                {
125                    let min_height = req_size_height;
126                    let max_height = req_size_height;
127                    height_measure_mode = MeasureMode::Exactly;
128                    (min_height, max_height)
129                } else {
130                    let min_height = if !is_specified(min.height) {
131                        Len::zero()
132                    } else {
133                        min.height
134                    };
135                    let max_height = max.height;
136                    (min_height, max_height)
137                };
138                let mut size_from_cache = false;
139                if self.node_type() == NodeType::Text {
140                    if let Some(cache) = unsafe { self.measure_cache() }.as_mut() {
141                        if let Some(size_cache) = cache.get(&(
142                            OptionSize::new(
143                                OptionNum::some(min_width).to_hashable(),
144                                OptionNum::some(min_height).to_hashable(),
145                            ),
146                            OptionSize::new(
147                                OptionNum::some(max_width).to_hashable(),
148                                OptionNum::some(max_height).to_hashable(),
149                            ),
150                            OptionSize::new(
151                                max_content.width.to_hashable(),
152                                max_content.height.to_hashable(),
153                            ),
154                        )) {
155                            size = *size_cache;
156                            size_from_cache = true;
157                        }
158                    }
159                }
160                if !size_from_cache {
161                    let measure_size = func(
162                        convert_node_ref_to_ptr(self),
163                        max_width,
164                        width_measure_mode,
165                        max_height,
166                        height_measure_mode,
167                        min_width,
168                        min_height,
169                        max_content.width.unwrap_or(max_width),
170                        max_content.height.unwrap_or(max_height),
171                    );
172                    let width = if is_specified(measure_size.width) {
173                        measure_size.width
174                    } else {
175                        Len::zero()
176                    };
177                    let height = if is_specified(measure_size.height) {
178                        measure_size.height
179                    } else {
180                        Len::zero()
181                    };
182                    let measure_size = Size::new(width, height);
183                    size = Size::new(
184                        measure_size.width.clamp(min.width, max.width),
185                        measure_size.height.clamp(min.height, max.height),
186                    );
187                    if self.node_type() == NodeType::Text {
188                        if let Some(cache) = unsafe { self.measure_cache() }.as_mut() {
189                            cache.put(
190                                (
191                                    OptionSize::new(
192                                        OptionNum::some(min_width),
193                                        OptionNum::some(min_height),
194                                    ),
195                                    OptionSize::new(
196                                        OptionNum::some(max_width),
197                                        OptionNum::some(max_height),
198                                    ),
199                                    OptionSize::new(
200                                        max_content.width.to_hashable(),
201                                        max_content.height.to_hashable(),
202                                    ),
203                                ),
204                                size,
205                            );
206                        }
207                    }
208                }
209            };
210        }
211        let mut baseline = size.to_vector();
212        let mut baseline_from_cache = false;
213        if self.node_type() == NodeType::Text {
214            if let Some(cache) = unsafe { self.baseline_cache() }.as_mut() {
215                if let Some(baseline_cache) = cache.get(&Size::new(size.width, size.height)) {
216                    baseline_from_cache = true;
217                    baseline = Vector::new(Len::zero(), *baseline_cache);
218                }
219            }
220        }
221        if !baseline_from_cache {
222            if let Some(func) = unsafe { self.baseline_func() } {
223                let ret = func(convert_node_ref_to_ptr(self), size.width, size.height);
224                baseline = Vector::new(Len::zero(), ret);
225                if let Some(cache) = unsafe { self.baseline_cache() }.as_mut() {
226                    cache.put(Size::new(size.width, size.height), ret);
227                }
228            }
229        }
230        MeasureResult {
231            size,
232            first_baseline_ascent: baseline,
233            last_baseline_ascent: baseline,
234        }
235    }
236
237    #[inline]
238    fn measure_inline_unit(
239        &self,
240        env: &mut Self::Env,
241        req_size: OptionSize<Self::Length>,
242        min: Size<Self::Length>,
243        max: Size<Self::Length>,
244        max_content: OptionSize<Self::Length>,
245        sizing_mode: SizingMode,
246    ) -> MeasureResult<Self::Length> {
247        self.measure_block_size(env, req_size, min, max, max_content, false, sizing_mode)
248    }
249}
250
251impl LayoutTreeVisitor<Node> for Node {
252    #[inline]
253    fn parent(&self) -> Option<&Node> {
254        unsafe { Node::parent(self) }
255    }
256
257    #[inline]
258    fn for_each_child<'a, 'b: 'a, F>(&'b self, f: F)
259    where
260        F: FnMut(&'a Node, usize),
261        Node: 'a,
262    {
263        unsafe { self.for_each_child_node(f) }
264    }
265
266    #[inline]
267    fn children_len(&self) -> usize {
268        Node::children_len(self)
269    }
270
271    #[inline]
272    fn child_at(&self, index: usize) -> Option<&Node> {
273        unsafe { self.get_child_at(index) }
274    }
275
276    #[inline]
277    fn children_iter<'a, 'b: 'a>(&'b self) -> impl Iterator<Item = &'a Node>
278    where
279        Node: 'a,
280    {
281        unsafe { self.children().into_iter() }
282    }
283}
284#[derive(Debug, Clone)]
285pub struct LayoutInlineUnit {
286    offset: Point<Len>,
287    size: Size<Len>,
288    first_baseline_ascent: Vector<Len>,
289    last_baseline_ascent: Vector<Len>,
290}
291
292impl LayoutInlineUnit {
293    fn to_tuple(&self) -> (Point<Len>, MeasureResult<Len>) {
294        (
295            self.offset,
296            MeasureResult {
297                size: self.size,
298                first_baseline_ascent: self.first_baseline_ascent,
299                last_baseline_ascent: self.last_baseline_ascent,
300            },
301        )
302    }
303}
304
305impl InlineUnit<Node> for LayoutInlineUnit {
306    type Env = Env;
307    fn new(_env: &mut Env, _node: &Node, res: MeasureResult<Len>) -> Self {
308        Self {
309            offset: Point::zero(),
310            size: res.size,
311            first_baseline_ascent: res.first_baseline_ascent,
312            last_baseline_ascent: res.last_baseline_ascent,
313        }
314    }
315}
316
317#[derive(Debug, Clone)]
318struct Line {
319    inline_units: Vec<LayoutInlineUnit>,
320    total_inline_size: Len,
321    total_block_size: Len,
322    block_start: Len,
323    inline_offset: Len,
324    first_baseline_ascent: Vector<Len>,
325    // text_align: TextAlign,
326}
327
328impl Default for Line {
329    fn default() -> Self {
330        Self {
331            inline_units: vec![],
332            total_inline_size: Len::zero(),
333            total_block_size: Len::zero(),
334            block_start: Len::zero(),
335            inline_offset: Len::zero(),
336            first_baseline_ascent: Vector::default(),
337            // text_align: TextAlign::Start,
338        }
339    }
340}
341
342impl Line {
343    fn is_empty(&self) -> bool {
344        self.inline_units.is_empty()
345    }
346
347    fn collect_inline_unit(&mut self, mut inline_unit: LayoutInlineUnit, margin: EdgeOption<Len>) {
348        inline_unit.offset.x += self.total_inline_size + margin.left.or_zero();
349        inline_unit.offset.y += self.block_start + margin.top.or_zero();
350        self.total_inline_size += inline_unit.size.width + margin.horizontal();
351        self.total_block_size = self
352            .total_block_size
353            .max(inline_unit.size.height + margin.vertical());
354        self.first_baseline_ascent = self
355            .first_baseline_ascent
356            .max(inline_unit.first_baseline_ascent);
357        self.inline_units.push(inline_unit);
358    }
359
360    fn adjust_inline_offset(&mut self) {
361        self.inline_units.iter_mut().for_each(|inline_unit| {
362            inline_unit.offset.x += self.inline_offset;
363        })
364    }
365
366    fn adjust_block_offset(&mut self) {
367        // TODO affected by vertical-align
368        self.inline_units.iter_mut().for_each(|inline_unit| {
369            let max_baseline = self.first_baseline_ascent.y;
370            let self_baseline = inline_unit.first_baseline_ascent.y;
371            inline_unit.offset.y += max_baseline - self_baseline;
372        })
373    }
374
375    fn set_inline_offset(&mut self, inline_offset: Len) {
376        self.inline_offset = inline_offset
377    }
378}
379
380pub struct LayoutInlineMeasure {}
381impl InlineMeasure<Node> for LayoutInlineMeasure {
382    type InlineUnit = LayoutInlineUnit;
383    type Env = Env;
384
385    fn block_size(
386        _env: &mut Env,
387        block_node: &Node,
388        inline_nodes: Vec<InlineUnitMetadata<Node>>,
389        req_size: OptionSize<Len>,
390        _max_content_with_max_size: OptionSize<Len>,
391        _update_position: bool,
392        sizing_mode: SizingMode,
393    ) -> (Size<Len>, Vec<(Point<Len>, MeasureResult<Len>)>) {
394        let suggested_width = req_size.width;
395        let suggested_height = req_size.height;
396        if inline_nodes.is_empty() {
397            return (
398                Size::new(
399                    suggested_width.unwrap_or(Len::zero()),
400                    suggested_height.unwrap_or(Len::zero()),
401                ),
402                Vec::with_capacity(0),
403            );
404        }
405        let mut lines: Vec<Line> = vec![];
406        let mut prev_line_block_start = Len::zero();
407        let mut current_line = Line::default();
408        if let Some(suggested_width) = suggested_width.val() {
409            inline_nodes
410                .into_iter()
411                .for_each(|InlineUnitMetadata { unit, margin }| {
412                    if (current_line.total_inline_size + unit.size.width + margin.horizontal()
413                        > suggested_width)
414                        && !current_line.is_empty()
415                    {
416                        prev_line_block_start += current_line.total_block_size;
417                        lines.push(current_line.clone());
418                        current_line = Line::default();
419                        current_line.block_start = prev_line_block_start;
420                    }
421                    current_line.collect_inline_unit(unit, margin);
422                });
423        } else {
424            inline_nodes
425                .into_iter()
426                .for_each(|InlineUnitMetadata { unit, margin }| {
427                    current_line.collect_inline_unit(unit, margin);
428                });
429        }
430        if !current_line.is_empty() {
431            lines.push(current_line.clone());
432        }
433        let (mut block_width, mut block_height) = (Len::zero(), Len::zero());
434        lines.iter_mut().for_each(|line| {
435            block_width = block_width.max(line.total_inline_size);
436            block_height += line.total_block_size;
437            line.adjust_block_offset();
438        });
439        let block_size = match sizing_mode {
440            SizingMode::Normal => Size::new(
441                suggested_width.unwrap_or(block_width),
442                suggested_height.unwrap_or(block_height),
443            ),
444            SizingMode::MinContent => Size::new(block_width, block_height),
445            SizingMode::MaxContent => Size::new(block_width, block_height),
446        };
447        if let Some(suggested_width) = suggested_width.val() {
448            if suggested_width > block_width {
449                let text_align = block_node.style().text_align();
450                match text_align {
451                    TextAlign::Start | TextAlign::Left => {}
452                    TextAlign::End | TextAlign::Right => lines.iter_mut().for_each(|line| {
453                        let inline_offset = suggested_width - line.total_inline_size;
454                        line.set_inline_offset(inline_offset);
455                        line.adjust_inline_offset()
456                    }),
457                    TextAlign::Center => lines.iter_mut().for_each(|line| {
458                        let inline_offset = (suggested_width - line.total_inline_size).div_f32(2.);
459                        line.set_inline_offset(inline_offset);
460                        line.adjust_inline_offset()
461                    }),
462                    TextAlign::Justify => {}
463                    TextAlign::JustifyAll => {}
464                    TextAlign::MatchParent => {}
465                }
466            }
467        }
468        let detailed_position = lines
469            .into_iter()
470            .flat_map(|line| {
471                line.inline_units
472                    .into_iter()
473                    .map(|inline_unit| inline_unit.to_tuple())
474            })
475            .collect();
476        (block_size, detailed_position)
477    }
478}
479
480impl LayoutStyle<Len> for Node {
481    #[inline]
482    fn display(&self) -> Display {
483        self.style_manager().display()
484    }
485
486    #[inline]
487    fn position(&self) -> Position {
488        self.style_manager().position()
489    }
490
491    #[inline]
492    fn box_sizing(&self) -> BoxSizing {
493        self.style_manager().box_sizing()
494    }
495
496    #[inline]
497    fn direction(&self) -> Direction {
498        self.style_manager().direction()
499    }
500
501    #[inline]
502    fn writing_mode(&self) -> WritingMode {
503        self.style_manager().writing_mode()
504    }
505
506    #[inline]
507    fn flex_direction(&self) -> FlexDirection {
508        self.style_manager().flex_direction()
509    }
510
511    #[inline]
512    fn flex_wrap(&self) -> FlexWrap {
513        self.style_manager().flex_wrap()
514    }
515
516    #[inline]
517    fn flex_grow(&self) -> f32 {
518        self.style_manager().flex_grow()
519    }
520
521    #[inline]
522    fn flex_shrink(&self) -> f32 {
523        self.style_manager().flex_shrink()
524    }
525
526    #[inline]
527    fn align_items(&self) -> AlignItems {
528        self.style_manager().align_items()
529    }
530
531    #[inline]
532    fn align_self(&self) -> AlignSelf {
533        self.style_manager().align_self()
534    }
535
536    #[inline]
537    fn align_content(&self) -> AlignContent {
538        self.style_manager().align_content()
539    }
540
541    #[inline]
542    fn justify_content(&self) -> JustifyContent {
543        self.style_manager().justify_content()
544    }
545
546    #[inline]
547    fn left(&self) -> Length {
548        self.style_manager().left()
549    }
550
551    #[inline]
552    fn right(&self) -> Length {
553        self.style_manager().right()
554    }
555
556    #[inline]
557    fn top(&self) -> Length {
558        self.style_manager().top()
559    }
560
561    #[inline]
562    fn bottom(&self) -> Length {
563        self.style_manager().bottom()
564    }
565
566    #[inline]
567    fn border_left(&self) -> Length {
568        self.style_manager().border_left()
569    }
570
571    #[inline]
572    fn border_right(&self) -> Length {
573        self.style_manager().border_right()
574    }
575
576    #[inline]
577    fn border_top(&self) -> Length {
578        self.style_manager().border_top()
579    }
580
581    #[inline]
582    fn border_bottom(&self) -> Length {
583        self.style_manager().border_bottom()
584    }
585
586    #[inline]
587    fn margin_left(&self) -> Length {
588        self.style_manager().margin_left()
589    }
590
591    #[inline]
592    fn margin_right(&self) -> Length {
593        self.style_manager().margin_right()
594    }
595
596    #[inline]
597    fn margin_top(&self) -> Length {
598        self.style_manager().margin_top()
599    }
600
601    #[inline]
602    fn margin_bottom(&self) -> Length {
603        self.style_manager().margin_bottom()
604    }
605
606    #[inline]
607    fn padding_left(&self) -> Length {
608        self.style_manager().padding_left()
609    }
610
611    #[inline]
612    fn padding_right(&self) -> Length {
613        self.style_manager().padding_right()
614    }
615
616    #[inline]
617    fn padding_top(&self) -> Length {
618        self.style_manager().padding_top()
619    }
620
621    #[inline]
622    fn padding_bottom(&self) -> Length {
623        self.style_manager().padding_bottom()
624    }
625
626    #[inline]
627    fn flex_basis(&self) -> Length {
628        self.style_manager().flex_basis()
629    }
630
631    #[inline]
632    fn width(&self) -> Length {
633        self.style_manager().width()
634    }
635
636    #[inline]
637    fn height(&self) -> Length {
638        self.style_manager().height()
639    }
640
641    #[inline]
642    fn min_width(&self) -> Length {
643        self.style_manager().min_width()
644    }
645
646    #[inline]
647    fn min_height(&self) -> Length {
648        self.style_manager().min_height()
649    }
650
651    #[inline]
652    fn max_width(&self) -> Length {
653        self.style_manager().max_width()
654    }
655
656    #[inline]
657    fn max_height(&self) -> Length {
658        self.style_manager().max_height()
659    }
660
661    #[inline]
662    fn aspect_ratio(&self) -> Option<f32> {
663        self.style_manager().aspect_ratio()
664    }
665
666    #[inline]
667    fn order(&self) -> i32 {
668        self.style_manager().order()
669    }
670
671    #[inline]
672    fn text_align(&self) -> TextAlign {
673        self.style_manager().text_align()
674    }
675
676    #[inline]
677    fn row_gap(&self) -> Length {
678        self.style_manager().row_gap()
679    }
680
681    #[inline]
682    fn column_gap(&self) -> Length {
683        self.style_manager().column_gap()
684    }
685    #[inline]
686    fn grid_template_rows(&self) -> LayoutGridTemplate {
687        self.style_manager().grid_template_rows()
688    }
689
690    #[inline]
691    fn grid_template_columns(&self) -> LayoutGridTemplate {
692        self.style_manager().grid_template_columns()
693    }
694
695    #[inline]
696    fn grid_auto_flow(&self) -> GridAutoFlow {
697        self.style_manager().grid_auto_flow()
698    }
699
700    #[inline]
701    fn grid_auto_rows(&self) -> LayoutGridAuto {
702        self.style_manager().grid_auto_rows()
703    }
704
705    #[inline]
706    fn grid_auto_columns(&self) -> LayoutGridAuto {
707        self.style_manager().grid_auto_columns()
708    }
709
710    #[inline]
711    fn justify_items(&self) -> JustifyItems {
712        self.style_manager().justify_items()
713    }
714
715    #[inline]
716    fn justify_self(&self) -> JustifySelf {
717        self.style_manager().justify_self()
718    }
719}