taitank/
node.rs

1// 节点核心实现
2
3use std::cell::RefCell;
4use std::rc::{Rc, Weak};
5use std::sync::Arc;
6
7use crate::cache::TaitankLayoutCache;
8use crate::config::{TaitankConfig, TaitankConfigRef};
9use crate::flex::*;
10use crate::flexline::FlexLine;
11use crate::style::TaitankStyle;
12use crate::util::*;
13
14pub type TaitankNodeRef = Rc<RefCell<TaitankNode>>;
15pub type WeakTaitankNodeRef = Weak<RefCell<TaitankNode>>;
16
17pub type TaitankMeasureFunction =
18    Box<dyn Fn(TaitankNodeRef, f32, MeasureMode, f32, MeasureMode, Option<*mut ()>) -> TaitankSize>;
19pub type TaitankDirtiedFunction = Box<dyn Fn(TaitankNodeRef)>;
20
21pub struct TaitankNode {
22    pub style: TaitankStyle,
23    pub layout_result: TaitankLayout,
24
25    pub context: Option<*mut ()>,
26    pub children: Vec<TaitankNodeRef>,
27    pub parent: Option<WeakTaitankNodeRef>,
28
29    pub measure: Option<TaitankMeasureFunction>,
30
31    pub is_frozen: bool,
32    pub is_dirty: bool,
33    pub has_new_layout: bool,
34    pub dirtied_function: Option<TaitankDirtiedFunction>,
35
36    pub layout_cache: TaitankLayoutCache,
37    pub in_initial_state: bool,
38    pub config: Option<TaitankConfigRef>,
39}
40
41impl TaitankNode {
42    pub fn new() -> TaitankNodeRef {
43        Self::new_with_config(Arc::new(TaitankConfig::default()))
44    }
45
46    pub fn new_with_config(config: TaitankConfigRef) -> TaitankNodeRef {
47        let mut node = Self {
48            style: TaitankStyle::new(),
49            layout_result: TaitankLayout::default(),
50            context: None,
51            children: Vec::new(),
52            parent: None,
53            measure: None,
54            is_frozen: false,
55            is_dirty: false,
56            has_new_layout: false,
57            dirtied_function: None,
58            layout_cache: TaitankLayoutCache::new(),
59            in_initial_state: true,
60            config: Some(config),
61        };
62        node.init_layout_result();
63        Rc::new(RefCell::new(node))
64    }
65
66    pub fn init_layout_result(&mut self) {
67        self.layout_result = TaitankLayout::default();
68        self.layout_cache.clear_cache();
69        self.in_initial_state = true;
70    }
71
72    pub fn reset(&mut self) -> bool {
73        if !self.children.is_empty() || self.parent.is_some() {
74            return false;
75        }
76        self.children.clear();
77        self.children.shrink_to_fit();
78        self.init_layout_result();
79        self.in_initial_state = true;
80        true
81    }
82
83    pub fn print_node(&self, indent: u32) {
84        let indent_str = " ".repeat(indent as usize);
85        let width = if self.layout_result.dim[0].is_nan() {
86            "NAN".to_string()
87        } else {
88            format!("{:.0}", self.layout_result.dim[0].round())
89        };
90        let height = if self.layout_result.dim[1].is_nan() {
91            "NAN".to_string()
92        } else {
93            format!("{:.0}", self.layout_result.dim[1].round())
94        };
95        let left = if self.layout_result.position[0].is_nan() {
96            "NAN".to_string()
97        } else {
98            format!("{:.0}", self.layout_result.position[0].round())
99        };
100        let top = if self.layout_result.position[1].is_nan() {
101            "NAN".to_string()
102        } else {
103            format!("{:.0}", self.layout_result.position[1].round())
104        };
105
106        // Simple style string representation
107        let style_str = format!("flex-direction:{:?};", self.style.flex_direction);
108
109        println!(
110            "{}<div layout=\"width:{}; height:{}; left:{}; top:{}\" style=\"{}\">",
111            indent_str, width, height, left, top, style_str
112        );
113
114        for child in &self.children {
115            child.borrow().print_node(indent + 4);
116        }
117
118        println!("{}</div>", indent_str);
119    }
120
121    pub fn set_parent(&mut self, parent: Option<WeakTaitankNodeRef>) {
122        self.parent = parent;
123    }
124
125    pub fn get_parent(&self) -> Option<TaitankNodeRef> {
126        self.parent.as_ref().and_then(|p| p.upgrade())
127    }
128
129    pub fn add_child(&mut self, child: TaitankNodeRef) {
130        // Create a self reference for parent
131        // Note: We can't use Rc::downgrade on self directly, so we'll set parent after child is added
132        self.children.push(child.clone());
133        // Set parent reference - this is a workaround since we need a weak reference to self
134        // In actual usage, the caller should handle parent-child relationships properly
135        self.mark_as_dirty();
136    }
137
138    pub fn insert_child(&mut self, child: TaitankNodeRef, index: usize) -> bool {
139        if index > self.children.len() {
140            return false;
141        }
142        self.children.insert(index, child);
143        self.mark_as_dirty();
144        true
145    }
146
147    pub fn get_child(&self, index: usize) -> Option<TaitankNodeRef> {
148        self.children.get(index).cloned()
149    }
150
151    pub fn remove_child(&mut self, child: &TaitankNodeRef) -> bool {
152        if let Some(pos) = self.children.iter().position(|c| Rc::ptr_eq(c, child)) {
153            self.children.remove(pos);
154            child.borrow_mut().set_parent(None);
155            child.borrow_mut().reset_layout_recursive(false);
156            self.mark_as_dirty();
157            true
158        } else {
159            false
160        }
161    }
162
163    pub fn child_count(&self) -> usize {
164        self.children.len()
165    }
166
167    pub fn set_display_type(&mut self, display_type: DisplayType) {
168        if self.style.display_type == display_type {
169            return;
170        }
171        self.style.display_type = display_type;
172        self.is_dirty = false;
173        self.mark_as_dirty();
174    }
175
176    pub fn set_has_new_layout(&mut self, has_new_layout: bool) {
177        self.has_new_layout = has_new_layout;
178    }
179
180    pub fn get_has_new_layout(&self) -> bool {
181        self.has_new_layout
182    }
183
184    pub fn mark_as_dirty(&mut self) {
185        if !self.is_dirty {
186            self.set_dirty(true);
187            if let Some(parent) = self.get_parent() {
188                parent.borrow_mut().mark_as_dirty();
189            }
190        }
191    }
192
193    pub fn set_dirty(&mut self, dirty: bool) {
194        if self.is_dirty == dirty {
195            return;
196        }
197        self.is_dirty = dirty;
198        if self.is_dirty {
199            self.layout_result.direction = TaitankDirection::Inherit;
200            self.is_frozen = false;
201            self.layout_cache.clear_cache();
202            if let Some(ref dirtied_fn) = self.dirtied_function {
203                let self_ref = Rc::new(RefCell::new(TaitankNode {
204                    style: self.style.clone(),
205                    layout_result: self.layout_result.clone(),
206                    context: self.context,
207                    children: Vec::new(),
208                    parent: None,
209                    measure: None,
210                    is_frozen: self.is_frozen,
211                    is_dirty: self.is_dirty,
212                    has_new_layout: self.has_new_layout,
213                    dirtied_function: None,
214                    layout_cache: TaitankLayoutCache::new(),
215                    in_initial_state: self.in_initial_state,
216                    config: self.config.clone(),
217                }));
218                dirtied_fn(self_ref);
219            }
220        }
221    }
222
223    pub fn set_dirtied_function(&mut self, dirtied_function: Option<TaitankDirtiedFunction>) {
224        self.dirtied_function = dirtied_function;
225    }
226
227    pub fn set_context(&mut self, context: Option<*mut ()>) {
228        self.context = context;
229    }
230
231    pub fn get_context(&self) -> Option<*mut ()> {
232        self.context
233    }
234
235    pub fn get_start_border(&self, axis: FlexDirection) -> f32 {
236        self.style.get_start_border(axis)
237    }
238
239    pub fn get_end_border(&self, axis: FlexDirection) -> f32 {
240        self.style.get_end_border(axis)
241    }
242
243    pub fn get_start_padding_and_border(&self, axis: FlexDirection) -> f32 {
244        self.style.get_start_padding(axis) + self.style.get_start_border(axis)
245    }
246
247    pub fn get_end_padding_and_border(&self, axis: FlexDirection) -> f32 {
248        self.style.get_end_padding(axis) + self.style.get_end_border(axis)
249    }
250
251    pub fn get_padding_and_border(&self, axis: FlexDirection) -> f32 {
252        self.get_start_padding_and_border(axis) + self.get_end_padding_and_border(axis)
253    }
254
255    pub fn get_margin(&self, axis: FlexDirection) -> f32 {
256        self.style.get_margin(axis)
257    }
258
259    pub fn get_start_margin(&self, axis: FlexDirection) -> f32 {
260        self.style.get_start_margin(axis)
261    }
262
263    pub fn get_end_margin(&self, axis: FlexDirection) -> f32 {
264        self.style.get_end_margin(axis)
265    }
266
267    pub fn is_auto_start_margin(&self, axis: FlexDirection) -> bool {
268        self.style.is_auto_start_margin(axis)
269    }
270
271    pub fn is_auto_end_margin(&self, axis: FlexDirection) -> bool {
272        self.style.is_auto_end_margin(axis)
273    }
274
275    pub fn set_layout_start_margin(&mut self, axis: FlexDirection, value: f32) {
276        let idx = K_AXIS_START[axis as usize] as usize;
277        if !is_defined(self.layout_result.margin[idx])
278            || !float_is_equal(self.layout_result.margin[idx], value)
279        {
280            self.layout_result.margin[idx] = value;
281        }
282    }
283
284    pub fn set_layout_end_margin(&mut self, axis: FlexDirection, value: f32) {
285        let idx = K_AXIS_END[axis as usize] as usize;
286        if !is_defined(self.layout_result.margin[idx])
287            || !float_is_equal(self.layout_result.margin[idx], value)
288        {
289            self.layout_result.margin[idx] = value;
290        }
291    }
292
293    pub fn get_layout_margin(&self, axis: FlexDirection) -> f32 {
294        self.get_layout_start_margin(axis) + self.get_layout_end_margin(axis)
295    }
296
297    pub fn get_layout_start_margin(&self, axis: FlexDirection) -> f32 {
298        let idx = K_AXIS_START[axis as usize] as usize;
299        if is_defined(self.layout_result.margin[idx]) {
300            self.layout_result.margin[idx]
301        } else {
302            0.0
303        }
304    }
305
306    pub fn get_layout_end_margin(&self, axis: FlexDirection) -> f32 {
307        let idx = K_AXIS_END[axis as usize] as usize;
308        if is_defined(self.layout_result.margin[idx]) {
309            self.layout_result.margin[idx]
310        } else {
311            0.0
312        }
313    }
314
315    pub fn resolve_relative_position(&self, axis: FlexDirection, for_axis_start: bool) -> f32 {
316        if for_axis_start {
317            self.style.get_start_position(axis)
318        } else {
319            self.style.get_end_position(axis)
320        }
321    }
322
323    pub fn set_layout_start_position(
324        &mut self,
325        axis: FlexDirection,
326        value: f32,
327        add_relative_position: bool,
328    ) {
329        let relative_pos = if add_relative_position {
330            self.resolve_relative_position(axis, true)
331        } else {
332            0.0
333        };
334        let final_value = if is_defined(relative_pos) {
335            value + relative_pos
336        } else {
337            value
338        };
339        let idx = K_AXIS_START[axis as usize] as usize;
340
341        if !float_is_equal(self.layout_result.cached_position[idx], final_value) {
342            self.layout_result.cached_position[idx] = final_value;
343            self.set_has_new_layout(true);
344        }
345        self.layout_result.position[idx] = final_value;
346    }
347
348    pub fn set_layout_end_position(
349        &mut self,
350        axis: FlexDirection,
351        value: f32,
352        add_relative_position: bool,
353    ) {
354        let relative_pos = if add_relative_position {
355            self.resolve_relative_position(axis, false)
356        } else {
357            0.0
358        };
359        let final_value = if is_defined(relative_pos) {
360            value + relative_pos
361        } else {
362            value
363        };
364        let idx = K_AXIS_END[axis as usize] as usize;
365
366        if !float_is_equal(self.layout_result.cached_position[idx], final_value) {
367            self.layout_result.cached_position[idx] = final_value;
368            self.set_has_new_layout(true);
369        }
370        self.layout_result.position[idx] = final_value;
371    }
372
373    pub fn get_layout_start_position(&self, axis: FlexDirection) -> f32 {
374        self.layout_result.position[K_AXIS_START[axis as usize] as usize]
375    }
376
377    pub fn get_layout_end_position(&self, axis: FlexDirection) -> f32 {
378        self.layout_result.position[K_AXIS_END[axis as usize] as usize]
379    }
380
381    pub fn resolve_main_axis(&self) -> FlexDirection {
382        let main_axis = self.style.flex_direction;
383        let direction = self.get_layout_direction();
384        if direction == TaitankDirection::Rtl {
385            match main_axis {
386                FlexDirection::Row => FlexDirection::RowReverse,
387                FlexDirection::RowReverse => FlexDirection::Row,
388                _ => main_axis,
389            }
390        } else {
391            main_axis
392        }
393    }
394
395    pub fn resolve_cross_axis(&self) -> FlexDirection {
396        let main_axis = self.style.flex_direction;
397        let direction = self.get_layout_direction();
398        let cross_axis = if is_row_direction(main_axis) {
399            if self.style.flex_wrap == FlexWrapMode::WrapReverse {
400                FlexDirection::ColumnReverse
401            } else {
402                FlexDirection::Column
403            }
404        } else if self.style.flex_wrap == FlexWrapMode::WrapReverse {
405            FlexDirection::RowReverse
406        } else {
407            FlexDirection::Row
408        };
409
410        if is_row_direction(cross_axis) && direction == TaitankDirection::Rtl {
411            match cross_axis {
412                FlexDirection::Row => FlexDirection::RowReverse,
413                FlexDirection::RowReverse => FlexDirection::Row,
414                _ => cross_axis,
415            }
416        } else {
417            cross_axis
418        }
419    }
420
421    pub fn get_node_align(&self, item: &TaitankNodeRef) -> FlexAlign {
422        let item_borrow = item.borrow();
423        if item_borrow.style.align_self == FlexAlign::Auto {
424            self.style.align_items
425        } else {
426            item_borrow.style.align_self
427        }
428    }
429
430    pub fn get_bound_axis(&self, axis: FlexDirection, value: f32) -> f32 {
431        let min = self.style.min_dim[K_AXIS_DIM[axis as usize] as usize];
432        let max = self.style.max_dim[K_AXIS_DIM[axis as usize] as usize];
433        let mut bound_value = value;
434        if is_defined(max) && max >= 0.0 && bound_value > max {
435            bound_value = max;
436        }
437        if is_defined(min) && min >= 0.0 && bound_value < min {
438            bound_value = min;
439        }
440        bound_value
441    }
442
443    pub fn set_config(&mut self, config: Option<TaitankConfigRef>) {
444        self.config = config;
445    }
446
447    pub fn get_config(&self) -> Option<TaitankConfigRef> {
448        self.config.clone()
449    }
450
451    pub fn get_main_axis_dimension(&self) -> f32 {
452        let main_axis = self.style.flex_direction;
453        if !self.is_layout_dimension_defined(main_axis) {
454            return VALUE_UNDEFINED;
455        }
456        self.get_layout_dimension(main_axis)
457    }
458
459    pub fn get_layout_dimension(&self, axis: FlexDirection) -> f32 {
460        if !self.is_layout_dimension_defined(axis) {
461            return VALUE_UNDEFINED;
462        }
463        self.layout_result.dim[K_AXIS_DIM[axis as usize] as usize]
464    }
465
466    pub fn is_layout_dimension_defined(&self, axis: FlexDirection) -> bool {
467        is_defined(self.layout_result.dim[K_AXIS_DIM[axis as usize] as usize])
468    }
469
470    pub fn set_layout_dimension(&mut self, axis: FlexDirection, value: f32) {
471        self.layout_result.dim[K_AXIS_DIM[axis as usize] as usize] = value;
472    }
473
474    pub fn set_layout_direction(&mut self, direction: TaitankDirection) {
475        self.layout_result.direction = direction;
476    }
477
478    pub fn get_layout_direction(&self) -> TaitankDirection {
479        self.layout_result.direction
480    }
481
482    pub fn reset_layout_recursive(&mut self, is_display_none: bool) {
483        if is_display_none {
484            self.layout_result = TaitankLayout::default();
485        } else {
486            for i in 0..4 {
487                self.layout_result.position[i] = 0.0;
488                self.layout_result.cached_position[i] = 0.0;
489            }
490        }
491        self.has_new_layout = false;
492        for child in self.children.iter() {
493            child.borrow_mut().reset_layout_recursive(is_display_none);
494        }
495    }
496
497    pub fn resolve_direction(&self, parent_direction: TaitankDirection) -> TaitankDirection {
498        if self.style.direction == TaitankDirection::Inherit {
499            if parent_direction != TaitankDirection::Inherit {
500                parent_direction
501            } else {
502                TaitankDirection::Ltr
503            }
504        } else {
505            self.style.direction
506        }
507    }
508
509    pub fn resolve_style_values(&mut self) {
510        let main_axis = self.resolve_main_axis();
511        let cross_axis = self.resolve_cross_axis();
512
513        self.set_layout_start_margin(main_axis, self.style.get_start_margin(main_axis));
514        self.set_layout_end_margin(main_axis, self.style.get_end_margin(main_axis));
515        self.set_layout_start_margin(cross_axis, self.style.get_start_margin(cross_axis));
516        self.set_layout_end_margin(cross_axis, self.style.get_end_margin(cross_axis));
517
518        self.layout_result.padding[K_AXIS_START[main_axis as usize] as usize] =
519            self.style.get_start_padding(main_axis);
520        self.layout_result.padding[K_AXIS_END[main_axis as usize] as usize] =
521            self.style.get_end_padding(main_axis);
522        self.layout_result.padding[K_AXIS_START[cross_axis as usize] as usize] =
523            self.style.get_start_padding(cross_axis);
524        self.layout_result.padding[K_AXIS_END[cross_axis as usize] as usize] =
525            self.style.get_end_padding(cross_axis);
526
527        self.layout_result.border[K_AXIS_START[main_axis as usize] as usize] =
528            self.style.get_start_border(main_axis);
529        self.layout_result.border[K_AXIS_END[main_axis as usize] as usize] =
530            self.style.get_end_border(main_axis);
531        self.layout_result.border[K_AXIS_START[cross_axis as usize] as usize] =
532            self.style.get_start_border(cross_axis);
533        self.layout_result.border[K_AXIS_END[cross_axis as usize] as usize] =
534            self.style.get_end_border(cross_axis);
535    }
536
537    pub fn cache_layout_or_measure_result(
538        &mut self,
539        available_size: TaitankSize,
540        measure_mode: TaitankSizeMode,
541        layout_action: FlexLayoutAction,
542    ) {
543        let result_size = TaitankSize::new(
544            self.layout_result.dim[Dimension::Width as usize],
545            self.layout_result.dim[Dimension::Height as usize],
546        );
547        self.layout_cache
548            .cache_result(available_size, result_size, measure_mode, layout_action);
549        if layout_action == FlexLayoutAction::Layout {
550            self.set_dirty(false);
551            self.set_has_new_layout(true);
552            self.in_initial_state = false;
553        }
554    }
555
556    pub fn layout_single_node(
557        &mut self,
558        available_width: f32,
559        width_measure_mode: MeasureMode,
560        available_height: f32,
561        height_measure_mode: MeasureMode,
562        layout_action: FlexLayoutAction,
563        layout_context: Option<*mut ()>,
564    ) {
565        if width_measure_mode == MeasureMode::Exactly && height_measure_mode == MeasureMode::Exactly
566        {
567            self.layout_result.dim[Dimension::Width as usize] =
568                available_width + self.get_padding_and_border(FlexDirection::Row);
569            self.layout_result.dim[Dimension::Height as usize] =
570                available_height + self.get_padding_and_border(FlexDirection::Column);
571        } else {
572            let mut dim = TaitankSize::new(0.0, 0.0);
573            let mut need_measure = true;
574
575            if let Some(parent) = self.get_parent() {
576                let parent_borrow = parent.borrow();
577                if self.style.flex_grow > 0.0
578                    && self.style.flex_shrink > 0.0
579                    && parent_borrow.child_count() == 1
580                    && !parent_borrow.style.is_dimension_auto(FlexDirection::Row)
581                    && !parent_borrow.style.is_dimension_auto(FlexDirection::Column)
582                {
583                    need_measure = false;
584                }
585            }
586
587            if !need_measure {
588                dim.width = available_width;
589                dim.height = available_height;
590            } else if let Some(ref measure_fn) = self.measure {
591                let self_ref = Rc::new(RefCell::new(TaitankNode {
592                    style: self.style.clone(),
593                    layout_result: self.layout_result.clone(),
594                    context: self.context,
595                    children: Vec::new(),
596                    parent: None,
597                    measure: None,
598                    is_frozen: self.is_frozen,
599                    is_dirty: self.is_dirty,
600                    has_new_layout: self.has_new_layout,
601                    dirtied_function: None,
602                    layout_cache: TaitankLayoutCache::new(),
603                    in_initial_state: self.in_initial_state,
604                    config: self.config.clone(),
605                }));
606                dim = measure_fn(
607                    self_ref,
608                    available_width,
609                    width_measure_mode,
610                    available_height,
611                    height_measure_mode,
612                    layout_context,
613                );
614            }
615
616            self.layout_result.dim[Dimension::Width as usize] = self.get_bound_axis(
617                FlexDirection::Row,
618                if width_measure_mode == MeasureMode::Exactly {
619                    available_width + self.get_padding_and_border(FlexDirection::Row)
620                } else {
621                    dim.width + self.get_padding_and_border(FlexDirection::Row)
622                },
623            );
624
625            self.layout_result.dim[Dimension::Height as usize] = self.get_bound_axis(
626                FlexDirection::Column,
627                if height_measure_mode == MeasureMode::Exactly {
628                    available_height + self.get_padding_and_border(FlexDirection::Column)
629                } else {
630                    dim.height + self.get_padding_and_border(FlexDirection::Column)
631                },
632            );
633        }
634
635        let available_size = TaitankSize::new(available_width, available_height);
636        let measure_mode = TaitankSizeMode {
637            width_measure_mode,
638            height_measure_mode,
639        };
640        self.cache_layout_or_measure_result(available_size, measure_mode, layout_action);
641    }
642
643    // 注意:这里简化了布局算法实现。完整实现需要参考 C++ 版本
644    // 由于代码量非常大(1500+ 行),这里提供一个基础框架
645    // 完整实现需要逐步完善各个布局步骤
646
647    pub fn layout(
648        &mut self,
649        parent_width: f32,
650        parent_height: f32,
651        config: TaitankConfigRef,
652        parent_direction: TaitankDirection,
653        layout_context: Option<*mut ()>,
654    ) {
655        // 这里需要实现完整的布局算法
656        // 由于代码量非常大,先提供基础框架
657        // TODO: 实现完整的布局算法
658        self.layout_impl(
659            parent_width,
660            parent_height,
661            parent_direction,
662            FlexLayoutAction::Layout,
663            layout_context,
664        );
665
666        let main_axis = self.resolve_main_axis();
667        let cross_axis = self.resolve_cross_axis();
668        self.set_layout_start_position(main_axis, self.get_start_margin(main_axis), true);
669        self.set_layout_end_position(main_axis, self.get_end_margin(main_axis), true);
670        self.set_layout_start_position(cross_axis, self.get_start_margin(cross_axis), true);
671        self.set_layout_end_position(cross_axis, self.get_end_margin(cross_axis), true);
672
673        let scale_factor = config.get_scale_factor();
674        self.convert_layout_result(0.0, 0.0, scale_factor);
675    }
676
677    pub fn layout_impl(
678        &mut self,
679        parent_width: f32,
680        parent_height: f32,
681        parent_direction: TaitankDirection,
682        layout_action: FlexLayoutAction,
683        layout_context: Option<*mut ()>,
684    ) {
685        // 布局算法的核心实现 - 参考 W3C CSS Flexbox 规范
686
687        // 1. 解析方向并更新样式值
688        let direction = self.resolve_direction(parent_direction);
689        if self.get_layout_direction() != direction {
690            self.set_layout_direction(direction);
691            self.layout_cache.clear_cache();
692            self.resolve_style_values();
693        }
694
695        let main_axis = self.style.flex_direction;
696        let perform_layout = layout_action == FlexLayoutAction::Layout;
697
698        // 2. 处理父尺寸,减去边距
699        let adjusted_parent_width = if is_defined(parent_width) {
700            let width = parent_width - self.get_margin(FlexDirection::Row);
701            if width >= 0.0 {
702                width
703            } else {
704                0.0
705            }
706        } else {
707            VALUE_UNDEFINED
708        };
709
710        let adjusted_parent_height = if is_defined(parent_height) {
711            let height = parent_height - self.get_margin(FlexDirection::Column);
712            if height >= 0.0 {
713                height
714            } else {
715                0.0
716            }
717        } else {
718            VALUE_UNDEFINED
719        };
720
721        // 3. 获取节点尺寸(考虑边界约束)
722        let node_width = if is_defined(self.style.dim[Dimension::Width as usize]) {
723            self.get_bound_axis(
724                FlexDirection::Row,
725                self.style.dim[Dimension::Width as usize],
726            )
727        } else {
728            VALUE_UNDEFINED
729        };
730
731        let node_height = if is_defined(self.style.dim[Dimension::Height as usize]) {
732            self.get_bound_axis(
733                FlexDirection::Column,
734                self.style.dim[Dimension::Height as usize],
735            )
736        } else {
737            VALUE_UNDEFINED
738        };
739
740        // 4. 如果是测量操作且节点尺寸已定义,直接返回
741        if layout_action == FlexLayoutAction::MeasureWidth && is_defined(node_width) {
742            self.layout_result.dim[Dimension::Width as usize] = node_width;
743            return;
744        }
745        if layout_action == FlexLayoutAction::MeasureHeight && is_defined(node_height) {
746            self.layout_result.dim[Dimension::Height as usize] = node_height;
747            return;
748        }
749
750        // 5. 计算可用空间
751        let mut available_width = VALUE_UNDEFINED;
752        if is_defined(node_width) {
753            available_width = node_width - self.get_padding_and_border(FlexDirection::Row);
754        } else if is_defined(adjusted_parent_width) {
755            available_width =
756                adjusted_parent_width - self.get_padding_and_border(FlexDirection::Row);
757        }
758
759        let mut available_height = VALUE_UNDEFINED;
760        if is_defined(node_height) {
761            available_height = node_height - self.get_padding_and_border(FlexDirection::Column);
762        } else if is_defined(adjusted_parent_height) {
763            available_height =
764                adjusted_parent_height - self.get_padding_and_border(FlexDirection::Column);
765        }
766
767        // 6. 考虑最大尺寸限制
768        if is_defined(self.style.max_dim[Dimension::Width as usize]) {
769            if float_is_equal(
770                self.style.max_dim[Dimension::Width as usize],
771                self.style.min_dim[Dimension::Width as usize],
772            ) {
773                self.style.dim[Dimension::Width as usize] =
774                    self.style.min_dim[Dimension::Width as usize];
775            }
776            let max_dim_width = self.style.max_dim[Dimension::Width as usize]
777                - self.get_padding_and_border(FlexDirection::Row);
778            if max_dim_width >= 0.0 && max_dim_width < nan_as_inf(available_width) {
779                available_width = max_dim_width;
780            }
781        }
782
783        if is_defined(self.style.max_dim[Dimension::Height as usize]) {
784            if float_is_equal(
785                self.style.max_dim[Dimension::Height as usize],
786                self.style.min_dim[Dimension::Height as usize],
787            ) {
788                self.style.dim[Dimension::Height as usize] =
789                    self.style.min_dim[Dimension::Height as usize];
790            }
791            let max_dim_height = self.style.max_dim[Dimension::Height as usize]
792                - self.get_padding_and_border(FlexDirection::Column);
793            if max_dim_height >= 0.0 && max_dim_height < nan_as_inf(available_height) {
794                available_height = max_dim_height;
795            }
796        }
797
798        // 7. 确保可用空间不为负
799        available_width = if available_width < 0.0 {
800            0.0
801        } else {
802            available_width
803        };
804        available_height = if available_height < 0.0 {
805            0.0
806        } else {
807            available_height
808        };
809
810        // 8. 确定测量模式
811        let mut width_measure_mode = MeasureMode::Undefined;
812        if is_defined(self.style.dim[Dimension::Width as usize]) {
813            width_measure_mode = MeasureMode::Exactly;
814        } else if is_defined(available_width) {
815            if let Some(parent) = self.get_parent() {
816                let parent_borrow = parent.borrow();
817                if parent_borrow.style.is_overflow_scroll()
818                    && is_row_direction(parent_borrow.style.flex_direction)
819                {
820                    width_measure_mode = MeasureMode::Undefined;
821                    available_width = VALUE_AUTO;
822                } else {
823                    width_measure_mode = MeasureMode::AtMost;
824                }
825            } else {
826                width_measure_mode = MeasureMode::AtMost;
827            }
828        }
829
830        let mut height_measure_mode = MeasureMode::Undefined;
831        if is_defined(self.style.dim[Dimension::Height as usize]) {
832            height_measure_mode = MeasureMode::Exactly;
833        } else if is_defined(available_height) {
834            if let Some(parent) = self.get_parent() {
835                let parent_borrow = parent.borrow();
836                if parent_borrow.style.is_overflow_scroll()
837                    && is_column_direction(parent_borrow.style.flex_direction)
838                {
839                    height_measure_mode = MeasureMode::Undefined;
840                    available_height = VALUE_AUTO;
841                } else {
842                    height_measure_mode = MeasureMode::AtMost;
843                }
844            } else {
845                height_measure_mode = MeasureMode::AtMost;
846            }
847        }
848
849        let available_size = TaitankSize::new(available_width, available_height);
850        let measure_mode = TaitankSizeMode {
851            width_measure_mode,
852            height_measure_mode,
853        };
854
855        // 9. 检查缓存
856        if let Some(cache_result) = self.layout_cache.get_cached_measure_result(
857            available_size,
858            measure_mode,
859            layout_action,
860            self.measure.is_some(),
861        ) {
862            match layout_action {
863                FlexLayoutAction::MeasureWidth => {
864                    self.layout_result.dim[Dimension::Width as usize] =
865                        cache_result.result_size.width;
866                }
867                FlexLayoutAction::MeasureHeight => {
868                    self.layout_result.dim[Dimension::Height as usize] =
869                        cache_result.result_size.height;
870                }
871                FlexLayoutAction::Layout => {
872                    // 如果是测量节点且缓存来自测量操作,需要设置结果
873                    if cache_result.layout_action != FlexLayoutAction::Layout
874                        && self.measure.is_some()
875                    {
876                        self.layout_result.dim[Dimension::Width as usize] =
877                            cache_result.result_size.width;
878                        self.layout_result.dim[Dimension::Height as usize] =
879                            cache_result.result_size.height;
880                        self.cache_layout_or_measure_result(
881                            available_size,
882                            measure_mode,
883                            layout_action,
884                        );
885                    }
886                    self.set_dirty(false);
887                }
888            }
889            return;
890        }
891
892        // 10. 在布局前设置溢出标志
893        if layout_action == FlexLayoutAction::Layout {
894            self.layout_result.had_overflow = false;
895        }
896
897        // 11. 单节点布局处理
898        if self.children.is_empty() {
899            self.layout_single_node(
900                available_width,
901                width_measure_mode,
902                available_height,
903                height_measure_mode,
904                layout_action,
905                layout_context,
906            );
907            return;
908        }
909
910        // 12. 计算 Flex 基础尺寸
911        self.calculate_items_flex_basis(available_size, layout_context);
912
913        // 13. 收集 Flex 行
914        let mut flex_lines = Vec::new();
915        let sum_hypothetical_main_size_overflow =
916            self.collect_flex_lines(&mut flex_lines, available_size);
917
918        // 14. 计算最大行的主轴尺寸
919        let mut max_sum_items_main_size = 0.0;
920        for line in flex_lines.iter() {
921            if line.sum_hypothetical_main_size > max_sum_items_main_size {
922                max_sum_items_main_size = line.sum_hypothetical_main_size;
923            }
924        }
925
926        // 15. 确定容器的主轴尺寸
927        let container_inner_main_size;
928        if is_defined(self.style.dim[K_AXIS_DIM[main_axis as usize] as usize]) {
929            container_inner_main_size = self.style.dim[K_AXIS_DIM[main_axis as usize] as usize]
930                - self.get_padding_and_border(main_axis);
931        } else if sum_hypothetical_main_size_overflow {
932            let main_inner_size = if K_AXIS_DIM[main_axis as usize] == Dimension::Width {
933                available_size.width
934            } else {
935                available_size.height
936            };
937
938            if max_sum_items_main_size > main_inner_size && !self.style.is_overflow_scroll() {
939                // 创建一个临时节点引用来获取对齐方式(需要重构)
940                let self_rc = Rc::new(RefCell::new(TaitankNode {
941                    style: self.style.clone(),
942                    layout_result: self.layout_result.clone(),
943                    context: self.context,
944                    children: Vec::new(),
945                    parent: None,
946                    measure: None,
947                    is_frozen: self.is_frozen,
948                    is_dirty: self.is_dirty,
949                    has_new_layout: self.has_new_layout,
950                    dirtied_function: None,
951                    layout_cache: TaitankLayoutCache::new(),
952                    in_initial_state: self.in_initial_state,
953                    config: self.config.clone(),
954                }));
955
956                if let Some(parent) = self.get_parent() {
957                    let parent_borrow = parent.borrow();
958                    let node_align = parent_borrow.get_node_align(&self_rc);
959                    let parent_cross_axis = parent_borrow.resolve_cross_axis();
960                    if node_align == FlexAlign::Stretch
961                        && K_AXIS_DIM[main_axis as usize] == K_AXIS_DIM[parent_cross_axis as usize]
962                        && self.style.position_type != PositionType::Absolute
963                    {
964                        container_inner_main_size = main_inner_size;
965                    } else {
966                        container_inner_main_size = max_sum_items_main_size;
967                    }
968                } else {
969                    container_inner_main_size = max_sum_items_main_size;
970                }
971            } else {
972                container_inner_main_size = main_inner_size;
973            }
974        } else {
975            container_inner_main_size = max_sum_items_main_size;
976        }
977        self.layout_result.dim[K_AXIS_DIM[main_axis as usize] as usize] = self.get_bound_axis(
978            main_axis,
979            container_inner_main_size + self.get_padding_and_border(main_axis),
980        );
981
982        // 16. 如果是测量操作,提前返回
983        if (layout_action == FlexLayoutAction::MeasureWidth && is_row_direction(main_axis))
984            || (layout_action == FlexLayoutAction::MeasureHeight && is_column_direction(main_axis))
985        {
986            self.cache_layout_or_measure_result(available_size, measure_mode, layout_action);
987            return;
988        }
989
990        // 17. 确定项目主轴尺寸
991        self.determine_items_main_axis_size(&mut flex_lines, layout_action);
992
993        // 18. 确定交叉轴尺寸
994        let sum_lines_cross_size = self.determine_cross_axis_size(
995            &mut flex_lines,
996            available_size,
997            layout_action,
998            layout_context,
999        );
1000
1001        // 19. 如果不是布局操作,提前返回
1002        if !perform_layout {
1003            // 确定容器的交叉轴尺寸
1004            let cross_axis = self.resolve_cross_axis();
1005            let cross_dim_size =
1006                if is_defined(self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize]) {
1007                    self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize]
1008                } else {
1009                    sum_lines_cross_size + self.get_padding_and_border(cross_axis)
1010                };
1011            self.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize] =
1012                self.get_bound_axis(cross_axis, cross_dim_size);
1013            self.cache_layout_or_measure_result(available_size, measure_mode, layout_action);
1014            return;
1015        }
1016
1017        // 20. 主轴对齐
1018        self.main_axis_alignment(&mut flex_lines);
1019
1020        // 21. 交叉轴对齐
1021        self.cross_axis_alignment(&mut flex_lines);
1022
1023        // 22. 缓存布局结果
1024        self.cache_layout_or_measure_result(available_size, measure_mode, layout_action);
1025
1026        // 23. 布局固定定位项目
1027        self.layout_fixed_items(measure_mode, layout_context);
1028    }
1029
1030    pub fn calculate_items_flex_basis(
1031        &mut self,
1032        available_size: TaitankSize,
1033        layout_context: Option<*mut ()>,
1034    ) {
1035        let main_axis = self.style.flex_direction;
1036        for child in self.children.iter() {
1037            let mut child_borrow = child.borrow_mut();
1038            if child_borrow.style.display_type == DisplayType::None {
1039                child_borrow.reset_layout_recursive(true);
1040                continue;
1041            }
1042            if child_borrow.style.position_type == PositionType::Absolute {
1043                continue;
1044            }
1045
1046            // 计算 flex basis
1047            if is_defined(child_borrow.style.get_flex_basis())
1048                && is_defined(self.style.dim[K_AXIS_DIM[main_axis as usize] as usize])
1049            {
1050                child_borrow.layout_result.flex_base_size = child_borrow.style.get_flex_basis();
1051            } else if is_defined(child_borrow.style.dim[K_AXIS_DIM[main_axis as usize] as usize]) {
1052                child_borrow.layout_result.flex_base_size =
1053                    child_borrow.style.dim[K_AXIS_DIM[main_axis as usize] as usize];
1054            } else {
1055                let old_main_dim = child_borrow.style.get_dimension_by_axis(main_axis);
1056                let flex_basis = child_borrow.style.flex_basis;
1057                child_borrow
1058                    .style
1059                    .set_dimension_by_axis(main_axis, flex_basis);
1060                child_borrow.layout_impl(
1061                    available_size.width,
1062                    available_size.height,
1063                    self.get_layout_direction(),
1064                    if is_row_direction(main_axis) {
1065                        FlexLayoutAction::MeasureWidth
1066                    } else {
1067                        FlexLayoutAction::MeasureHeight
1068                    },
1069                    layout_context,
1070                );
1071                child_borrow
1072                    .style
1073                    .set_dimension_by_axis(main_axis, old_main_dim);
1074                child_borrow.layout_result.flex_base_size = if is_defined(
1075                    child_borrow.layout_result.dim[K_AXIS_DIM[main_axis as usize] as usize],
1076                ) {
1077                    child_borrow.layout_result.dim[K_AXIS_DIM[main_axis as usize] as usize]
1078                } else {
1079                    0.0
1080                };
1081            }
1082
1083            child_borrow.layout_result.hypothetical_main_axis_size =
1084                child_borrow.get_bound_axis(main_axis, child_borrow.layout_result.flex_base_size);
1085            child_borrow
1086                .layout_result
1087                .hypothetical_main_axis_margin_boxsize =
1088                child_borrow.layout_result.hypothetical_main_axis_size
1089                    + child_borrow.get_margin(main_axis);
1090        }
1091    }
1092
1093    pub fn collect_flex_lines(
1094        &mut self,
1095        flex_lines: &mut Vec<FlexLine>,
1096        available_size: TaitankSize,
1097    ) -> bool {
1098        let mut sum_hypothetical_main_size_overflow = false;
1099        let available_width = if K_AXIS_DIM[self.style.flex_direction as usize] == Dimension::Width
1100        {
1101            if is_undefined(available_size.width) {
1102                f32::INFINITY
1103            } else {
1104                available_size.width
1105            }
1106        } else if is_undefined(available_size.height) {
1107            f32::INFINITY
1108        } else {
1109            available_size.height
1110        };
1111
1112        let mut line: Option<FlexLine> = None;
1113        let items_size = self.children.len();
1114        let mut i = 0;
1115
1116        while i < items_size {
1117            let child = &self.children[i];
1118            let child_borrow = child.borrow();
1119            if child_borrow.style.position_type == PositionType::Absolute
1120                || child_borrow.style.display_type == DisplayType::None
1121            {
1122                if i == items_size - 1 {
1123                    if let Some(l) = line {
1124                        flex_lines.push(l);
1125                    }
1126                    break;
1127                }
1128                i += 1;
1129                continue;
1130            }
1131
1132            if line.is_none() {
1133                line = Some(FlexLine::new(Rc::new(RefCell::new(TaitankNode {
1134                    style: self.style.clone(),
1135                    layout_result: self.layout_result.clone(),
1136                    context: self.context,
1137                    children: Vec::new(),
1138                    parent: None,
1139                    measure: None,
1140                    is_frozen: self.is_frozen,
1141                    is_dirty: self.is_dirty,
1142                    has_new_layout: self.has_new_layout,
1143                    dirtied_function: None,
1144                    layout_cache: TaitankLayoutCache::new(),
1145                    in_initial_state: self.in_initial_state,
1146                    config: self.config.clone(),
1147                }))));
1148            }
1149
1150            let sum_size = line.as_ref().unwrap().sum_hypothetical_main_size
1151                + child_borrow
1152                    .layout_result
1153                    .hypothetical_main_axis_margin_boxsize;
1154            let left_space = available_width - sum_size;
1155            if left_space < 0.0 {
1156                sum_hypothetical_main_size_overflow = true;
1157            }
1158
1159            if self.style.flex_wrap == FlexWrapMode::NoWrap {
1160                line.as_mut().unwrap().add_item(child.clone());
1161                if i == items_size - 1 {
1162                    flex_lines.push(line.take().unwrap());
1163                    break;
1164                }
1165                i += 1;
1166            } else if left_space >= 0.0 || line.as_ref().unwrap().is_empty() {
1167                line.as_mut().unwrap().add_item(child.clone());
1168                if i == items_size - 1 {
1169                    flex_lines.push(line.take().unwrap());
1170                }
1171                i += 1;
1172            } else {
1173                flex_lines.push(line.take().unwrap());
1174            }
1175        }
1176
1177        sum_hypothetical_main_size_overflow
1178    }
1179
1180    pub fn determine_items_main_axis_size(
1181        &mut self,
1182        flex_lines: &mut [FlexLine],
1183        layout_action: FlexLayoutAction,
1184    ) {
1185        for line in flex_lines.iter_mut() {
1186            line.container_main_inner_size = self.get_layout_dimension(self.style.flex_direction)
1187                - self.get_padding_and_border(self.style.flex_direction);
1188            line.freeze_inflexible_items(layout_action);
1189            loop {
1190                if line.resolve_flexible_lengths() {
1191                    break;
1192                }
1193            }
1194        }
1195    }
1196
1197    pub fn determine_cross_axis_size(
1198        &mut self,
1199        flex_lines: &mut [FlexLine],
1200        available_size: TaitankSize,
1201        layout_action: FlexLayoutAction,
1202        layout_context: Option<*mut ()>,
1203    ) -> f32 {
1204        let main_axis = self.style.flex_direction;
1205        let cross_axis = self.resolve_cross_axis();
1206        let mut sum_lines_cross_size = 0.0;
1207
1208        let lines_count = flex_lines.len();
1209        let is_single_line = lines_count == 1;
1210        let cross_dim_defined =
1211            is_defined(self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize]);
1212
1213        // 计算每行的交叉轴尺寸
1214        for line in flex_lines.iter_mut() {
1215            let mut max_item_cross_size = 0.0;
1216
1217            for item in line.items.iter() {
1218                // 对于每个项目,计算其假设交叉轴尺寸
1219                // 先获取对齐方式(避免借用冲突)
1220                let node_align = {
1221                    let item_borrow = item.borrow();
1222                    if item_borrow.style.align_self == FlexAlign::Auto {
1223                        self.style.align_items
1224                    } else {
1225                        item_borrow.style.align_self
1226                    }
1227                };
1228
1229                let item_borrow = item.borrow_mut();
1230
1231                // 处理 stretch 对齐的项目(延迟布局)
1232                let mut current_layout_action = layout_action;
1233
1234                let should_delay_stretch = node_align == FlexAlign::Stretch
1235                    && item_borrow.style.is_dimension_auto(cross_axis)
1236                    && !item_borrow.style.is_auto_margin(cross_axis)
1237                    && layout_action == FlexLayoutAction::Layout;
1238
1239                // 设置主轴尺寸并执行布局
1240                let old_main_dim = item_borrow.style.get_dimension_by_axis(main_axis);
1241                let layout_dim_main = item_borrow.get_layout_dimension(main_axis);
1242                drop(item_borrow);
1243
1244                if should_delay_stretch {
1245                    // 延迟 stretch 项目的布局,稍后在步骤 11 中处理
1246                    current_layout_action = if K_AXIS_DIM[cross_axis as usize] == Dimension::Width {
1247                        FlexLayoutAction::MeasureWidth
1248                    } else {
1249                        FlexLayoutAction::MeasureHeight
1250                    };
1251                }
1252
1253                let mut item_borrow_mut = item.borrow_mut();
1254                item_borrow_mut
1255                    .style
1256                    .set_dimension_by_axis(main_axis, layout_dim_main);
1257                item_borrow_mut.layout_impl(
1258                    available_size.width,
1259                    available_size.height,
1260                    self.get_layout_direction(),
1261                    current_layout_action,
1262                    layout_context,
1263                );
1264                item_borrow_mut
1265                    .style
1266                    .set_dimension_by_axis(main_axis, old_main_dim);
1267
1268                // 传递溢出状态
1269                self.layout_result.had_overflow =
1270                    self.layout_result.had_overflow || item_borrow_mut.layout_result.had_overflow;
1271
1272                // 计算项目的交叉轴尺寸(包括边距)
1273                let item_out_cross_size = item_borrow_mut.get_layout_dimension(cross_axis)
1274                    + item_borrow_mut.get_margin(cross_axis);
1275                if item_out_cross_size > max_item_cross_size {
1276                    max_item_cross_size = item_out_cross_size;
1277                }
1278            }
1279
1280            // 应用边界约束
1281            max_item_cross_size = self.get_bound_axis(cross_axis, max_item_cross_size);
1282            line.line_cross_size = max_item_cross_size;
1283            sum_lines_cross_size += max_item_cross_size;
1284
1285            // 单行情况:如果容器交叉轴尺寸已定义,使用容器尺寸
1286            if is_single_line && cross_dim_defined {
1287                let inner_cross_size = self.get_bound_axis(
1288                    cross_axis,
1289                    self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize],
1290                ) - self.get_padding_and_border(cross_axis);
1291                line.line_cross_size = inner_cross_size;
1292                sum_lines_cross_size = inner_cross_size;
1293            }
1294        }
1295
1296        // 处理 align-content: stretch
1297        if is_defined(self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize])
1298            && self.style.align_content == FlexAlign::Stretch
1299        {
1300            let inner_cross_size = self.get_bound_axis(
1301                cross_axis,
1302                self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize],
1303            ) - self.get_padding_and_border(cross_axis);
1304            if sum_lines_cross_size < inner_cross_size {
1305                let extra_space_per_line =
1306                    (inner_cross_size - sum_lines_cross_size) / flex_lines.len() as f32;
1307                for line in flex_lines.iter_mut() {
1308                    line.line_cross_size += extra_space_per_line;
1309                }
1310                sum_lines_cross_size = inner_cross_size;
1311            }
1312        }
1313
1314        // 处理 align-self: stretch 的项目
1315        for line in flex_lines.iter_mut() {
1316            for item in line.items.iter() {
1317                // 先获取对齐方式(避免借用冲突)
1318                let node_align = {
1319                    let item_borrow = item.borrow();
1320                    if item_borrow.style.align_self == FlexAlign::Auto {
1321                        self.style.align_items
1322                    } else {
1323                        item_borrow.style.align_self
1324                    }
1325                };
1326
1327                let item_borrow = item.borrow_mut();
1328
1329                let should_stretch = node_align == FlexAlign::Stretch
1330                    && item_borrow.style.is_dimension_auto(cross_axis)
1331                    && !item_borrow.style.is_auto_margin(cross_axis);
1332
1333                if should_stretch {
1334                    // 设置交叉轴尺寸为行尺寸减去边距
1335                    let line_cross_size = line.line_cross_size;
1336                    let margin_cross = item_borrow.get_margin(cross_axis);
1337                    let old_main_dim = item_borrow.style.get_dimension_by_axis(main_axis);
1338                    let old_cross_dim = item_borrow.style.get_dimension_by_axis(cross_axis);
1339                    let layout_dim_main = item_borrow.get_layout_dimension(main_axis);
1340                    let layout_dim_cross = item_borrow.get_layout_dimension(cross_axis);
1341                    drop(item_borrow);
1342
1343                    let mut item_borrow_mut = item.borrow_mut();
1344                    item_borrow_mut.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize] =
1345                        item_borrow_mut.get_bound_axis(cross_axis, line_cross_size - margin_cross);
1346
1347                    // 重新布局以处理百分比尺寸的子项
1348                    item_borrow_mut
1349                        .style
1350                        .set_dimension_by_axis(main_axis, layout_dim_main);
1351                    item_borrow_mut
1352                        .style
1353                        .set_dimension_by_axis(cross_axis, layout_dim_cross);
1354                    item_borrow_mut.layout_impl(
1355                        available_size.width,
1356                        available_size.height,
1357                        self.get_layout_direction(),
1358                        layout_action,
1359                        layout_context,
1360                    );
1361                    item_borrow_mut
1362                        .style
1363                        .set_dimension_by_axis(main_axis, old_main_dim);
1364                    item_borrow_mut
1365                        .style
1366                        .set_dimension_by_axis(cross_axis, old_cross_dim);
1367                }
1368            }
1369        }
1370
1371        sum_lines_cross_size
1372    }
1373
1374    pub fn main_axis_alignment(&mut self, flex_lines: &mut [FlexLine]) {
1375        for line in flex_lines.iter_mut() {
1376            line.align_items();
1377        }
1378    }
1379
1380    pub fn cross_axis_alignment(&mut self, flex_lines: &mut [FlexLine]) {
1381        let cross_axis = self.resolve_cross_axis();
1382        let mut sum_lines_cross_size = 0.0;
1383        let lines_count = flex_lines.len();
1384
1385        // 处理交叉轴自动边距和项目对齐
1386        for line in flex_lines.iter_mut() {
1387            sum_lines_cross_size += line.line_cross_size;
1388
1389            for item in line.items.iter() {
1390                // 先获取对齐方式(避免借用冲突)
1391                let node_align = {
1392                    let item_borrow = item.borrow();
1393                    if item_borrow.style.align_self == FlexAlign::Auto {
1394                        self.style.align_items
1395                    } else {
1396                        item_borrow.style.align_self
1397                    }
1398                };
1399
1400                let mut item_borrow = item.borrow_mut();
1401
1402                // 13. 处理交叉轴自动边距
1403                let remaining_free_space = line.line_cross_size
1404                    - item_borrow.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize]
1405                    - item_borrow.get_margin(cross_axis);
1406
1407                if remaining_free_space > 0.0 {
1408                    // 如果剩余空间为正,分配自动边距
1409                    if item_borrow.is_auto_start_margin(cross_axis)
1410                        && item_borrow.is_auto_end_margin(cross_axis)
1411                    {
1412                        item_borrow.set_layout_start_margin(cross_axis, remaining_free_space / 2.0);
1413                        item_borrow.set_layout_end_margin(cross_axis, remaining_free_space / 2.0);
1414                    } else if item_borrow.is_auto_start_margin(cross_axis) {
1415                        item_borrow.set_layout_start_margin(cross_axis, remaining_free_space);
1416                    } else if item_borrow.is_auto_end_margin(cross_axis) {
1417                        item_borrow.set_layout_end_margin(cross_axis, remaining_free_space);
1418                    } else {
1419                        // 设置样式中的边距值
1420                        let start_margin = item_borrow.style.get_start_margin(cross_axis);
1421                        let end_margin = item_borrow.style.get_end_margin(cross_axis);
1422                        item_borrow.set_layout_start_margin(cross_axis, start_margin);
1423                        item_borrow.set_layout_end_margin(cross_axis, end_margin);
1424                    }
1425                } else {
1426                    // 设置样式中的边距值
1427                    let start_margin = item_borrow.style.get_start_margin(cross_axis);
1428                    let end_margin = item_borrow.style.get_end_margin(cross_axis);
1429                    item_borrow.set_layout_start_margin(cross_axis, start_margin);
1430                    item_borrow.set_layout_end_margin(cross_axis, end_margin);
1431                }
1432
1433                // 14. 根据 align-self 对齐项目
1434                let remaining_free_space_for_align = line.line_cross_size
1435                    - item_borrow.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize]
1436                    - item_borrow.get_layout_margin(cross_axis);
1437
1438                // 兜底:若前序步骤未对 stretch 项设置交叉轴尺寸,这里补齐
1439                if node_align == FlexAlign::Stretch
1440                    && item_borrow.style.is_dimension_auto(cross_axis)
1441                    && !item_borrow.style.is_auto_margin(cross_axis)
1442                    && item_borrow.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize]
1443                        == 0.0
1444                {
1445                    let target = line.line_cross_size - item_borrow.get_margin(cross_axis);
1446                    item_borrow.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize] =
1447                        item_borrow.get_bound_axis(cross_axis, target);
1448                }
1449
1450                let mut offset = item_borrow.get_layout_start_margin(cross_axis);
1451
1452                match node_align {
1453                    FlexAlign::Start => {
1454                        // 默认位置
1455                    }
1456                    FlexAlign::Center => {
1457                        offset += remaining_free_space_for_align / 2.0;
1458                    }
1459                    FlexAlign::End => {
1460                        offset += remaining_free_space_for_align;
1461                    }
1462                    // TODO: FlexAlign::BaseLine => {
1463                    //     // 基线对齐(需要额外支持)
1464                    // }
1465                    _ => {}
1466                }
1467
1468                // 设置交叉轴起始位置
1469                item_borrow.set_layout_start_position(cross_axis, offset, false);
1470            }
1471        }
1472
1473        // 15. 确定容器的交叉轴尺寸
1474        let cross_dim_size = if is_defined(self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize])
1475        {
1476            self.style.dim[K_AXIS_DIM[cross_axis as usize] as usize]
1477        } else {
1478            sum_lines_cross_size + self.get_padding_and_border(cross_axis)
1479        };
1480        self.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize] =
1481            self.get_bound_axis(cross_axis, cross_dim_size);
1482
1483        // 16. 根据 align-content 对齐所有行
1484        let inner_cross_size = self.layout_result.dim[K_AXIS_DIM[cross_axis as usize] as usize]
1485            - self.get_padding_and_border(cross_axis);
1486        let remaining_free_space = inner_cross_size - sum_lines_cross_size;
1487        let mut offset = self.get_start_padding_and_border(cross_axis);
1488        let mut space = 0.0;
1489
1490        match self.style.align_content {
1491            FlexAlign::Start => {
1492                // 默认位置
1493            }
1494            FlexAlign::Center => {
1495                offset += remaining_free_space / 2.0;
1496            }
1497            FlexAlign::End => {
1498                offset += remaining_free_space;
1499            }
1500            FlexAlign::SpaceBetween => {
1501                if lines_count > 1 {
1502                    space = remaining_free_space / (lines_count - 1) as f32;
1503                }
1504            }
1505            FlexAlign::SpaceAround => {
1506                space = remaining_free_space / lines_count as f32;
1507                offset += space / 2.0;
1508            }
1509            FlexAlign::SpaceEvenly => {
1510                space = remaining_free_space / (lines_count + 1) as f32;
1511                offset += space;
1512            }
1513            _ => {}
1514        }
1515
1516        // 更新每行的位置
1517        let mut current_offset = offset;
1518        for line in flex_lines.iter_mut() {
1519            for item in line.items.iter_mut() {
1520                let mut item_borrow = item.borrow_mut();
1521                let current_cross_pos = item_borrow.get_layout_start_position(cross_axis);
1522                item_borrow.set_layout_start_position(
1523                    cross_axis,
1524                    current_cross_pos + current_offset,
1525                    false,
1526                );
1527                let container_dim = self.get_layout_dimension(cross_axis);
1528                let item_dim = item_borrow.get_layout_dimension(cross_axis);
1529                let item_start_pos = item_borrow.get_layout_start_position(cross_axis);
1530                item_borrow.set_layout_end_position(
1531                    cross_axis,
1532                    container_dim - item_dim - item_start_pos,
1533                    false,
1534                );
1535            }
1536            current_offset += line.line_cross_size + space;
1537        }
1538    }
1539
1540    pub fn layout_fixed_items(
1541        &mut self,
1542        _measure_mode: TaitankSizeMode,
1543        layout_context: Option<*mut ()>,
1544    ) {
1545        let main_axis = self.resolve_main_axis();
1546        let cross_axis = self.resolve_cross_axis();
1547
1548        // 收集需要处理的绝对定位项目
1549        let mut absolute_items: Vec<(TaitankNodeRef, f32, f32)> = Vec::new();
1550
1551        for item in self.children.iter() {
1552            let item_borrow = item.borrow();
1553            // 对于 display none 的项目,重置其布局结果
1554            if item_borrow.style.display_type == DisplayType::None {
1555                drop(item_borrow);
1556                let mut item_borrow_mut = item.borrow_mut();
1557                item_borrow_mut.reset_layout_recursive(true);
1558                continue;
1559            }
1560            if item_borrow.style.position_type != PositionType::Absolute {
1561                continue;
1562            }
1563
1564            let item_old_style_dim_main_axis = item_borrow.style.get_dimension_by_axis(main_axis);
1565            let item_old_style_dim_cross_axis = item_borrow.style.get_dimension_by_axis(cross_axis);
1566            drop(item_borrow);
1567
1568            absolute_items.push((
1569                item.clone(),
1570                item_old_style_dim_main_axis,
1571                item_old_style_dim_cross_axis,
1572            ));
1573        }
1574
1575        // 处理每个绝对定位项目
1576        for (item, item_old_style_dim_main_axis, item_old_style_dim_cross_axis) in absolute_items {
1577            let parent_width = self.get_layout_dimension(FlexDirection::Row)
1578                - self.get_padding_and_border(FlexDirection::Row);
1579            let parent_height = self.get_layout_dimension(FlexDirection::Column)
1580                - self.get_padding_and_border(FlexDirection::Column);
1581
1582            let mut item_borrow_mut = item.borrow_mut();
1583
1584            // 如果主轴尺寸未定义,但起始和结束位置都已定义,计算尺寸
1585            if is_undefined(item_old_style_dim_main_axis)
1586                && is_defined(item_borrow_mut.style.get_start_position(main_axis))
1587                && is_defined(item_borrow_mut.style.get_end_position(main_axis))
1588            {
1589                let container_dim = self.get_layout_dimension(main_axis);
1590                let start_border = self.style.get_start_border(main_axis);
1591                let end_border = self.style.get_end_border(main_axis);
1592                let start_pos = item_borrow_mut.style.get_start_position(main_axis);
1593                let end_pos = item_borrow_mut.style.get_end_position(main_axis);
1594                let margin = item_borrow_mut.get_margin(main_axis);
1595                item_borrow_mut.style.set_dimension_by_axis(
1596                    main_axis,
1597                    container_dim - start_border - end_border - start_pos - end_pos - margin,
1598                );
1599            }
1600
1601            // 如果交叉轴尺寸未定义,但起始和结束位置都已定义,计算尺寸
1602            if is_undefined(item_old_style_dim_cross_axis)
1603                && is_defined(item_borrow_mut.style.get_start_position(cross_axis))
1604                && is_defined(item_borrow_mut.style.get_end_position(cross_axis))
1605            {
1606                let container_dim = self.get_layout_dimension(cross_axis);
1607                let start_border = self.style.get_start_border(cross_axis);
1608                let end_border = self.style.get_end_border(cross_axis);
1609                let start_pos = item_borrow_mut.style.get_start_position(cross_axis);
1610                let end_pos = item_borrow_mut.style.get_end_position(cross_axis);
1611                let margin = item_borrow_mut.get_margin(cross_axis);
1612                item_borrow_mut.style.set_dimension_by_axis(
1613                    cross_axis,
1614                    container_dim - start_border - end_border - start_pos - end_pos - margin,
1615                );
1616            }
1617
1618            // 执行布局
1619            item_borrow_mut.layout_impl(
1620                parent_width,
1621                parent_height,
1622                self.get_layout_direction(),
1623                FlexLayoutAction::Layout,
1624                layout_context,
1625            );
1626
1627            // 恢复项目的样式值
1628            item_borrow_mut
1629                .style
1630                .set_dimension_by_axis(main_axis, item_old_style_dim_main_axis);
1631            item_borrow_mut
1632                .style
1633                .set_dimension_by_axis(cross_axis, item_old_style_dim_cross_axis);
1634            drop(item_borrow_mut);
1635
1636            // 布局完成后,计算固定项目的位置
1637            // 1) 主轴
1638            self.calculate_fixed_item_position(&item, main_axis);
1639            // 2) 交叉轴
1640            self.calculate_fixed_item_position(&item, cross_axis);
1641        }
1642    }
1643
1644    pub fn calculate_fixed_item_position(&mut self, item: &TaitankNodeRef, axis: FlexDirection) {
1645        let item_borrow = item.borrow();
1646
1647        if is_defined(item_borrow.style.get_start_position(axis)) {
1648            let start_pos = item_borrow.style.get_start_position(axis);
1649            let start_border = self.get_start_border(axis);
1650            let start_margin = item_borrow.get_layout_start_margin(axis);
1651            drop(item_borrow);
1652
1653            let mut item_borrow_mut = item.borrow_mut();
1654            item_borrow_mut.set_layout_start_position(
1655                axis,
1656                start_border + start_margin + start_pos,
1657                false,
1658            );
1659            let container_dim = self.get_layout_dimension(axis);
1660            let item_dim = item_borrow_mut.get_layout_dimension(axis);
1661            let item_start_pos = item_borrow_mut.get_layout_start_position(axis);
1662            item_borrow_mut.set_layout_end_position(
1663                axis,
1664                container_dim - item_dim - item_start_pos,
1665                false,
1666            );
1667        } else if is_defined(item_borrow.style.get_end_position(axis)) {
1668            let end_pos = item_borrow.style.get_end_position(axis);
1669            let end_border = self.get_end_border(axis);
1670            let end_margin = item_borrow.get_layout_end_margin(axis);
1671            drop(item_borrow);
1672
1673            let mut item_borrow_mut = item.borrow_mut();
1674            item_borrow_mut.set_layout_end_position(axis, end_border + end_margin + end_pos, false);
1675            let container_dim = self.get_layout_dimension(axis);
1676            let item_dim = item_borrow_mut.get_layout_dimension(axis);
1677            let item_end_pos = item_borrow_mut.get_layout_end_position(axis);
1678            item_borrow_mut.set_layout_start_position(
1679                axis,
1680                container_dim - item_dim - item_end_pos,
1681                false,
1682            );
1683        } else {
1684            // 如果起始和结束位置都未定义,使用对齐方式
1685            let remaining_free_space = self.get_layout_dimension(axis)
1686                - self.get_padding_and_border(axis)
1687                - item_borrow.get_layout_dimension(axis);
1688            let mut offset = self.get_start_padding_and_border(axis);
1689
1690            let align_mode = if axis == self.resolve_main_axis() {
1691                self.style.justify_content
1692            } else {
1693                let item_borrow = item.borrow();
1694                if item_borrow.style.align_self == FlexAlign::Auto {
1695                    self.style.align_items
1696                } else {
1697                    item_borrow.style.align_self
1698                }
1699            };
1700
1701            drop(item_borrow);
1702            let mut item_borrow_mut = item.borrow_mut();
1703
1704            match align_mode {
1705                FlexAlign::Start => {
1706                    // 默认位置
1707                }
1708                FlexAlign::Center => {
1709                    offset += remaining_free_space / 2.0;
1710                }
1711                FlexAlign::End => {
1712                    offset += remaining_free_space;
1713                }
1714                _ => {}
1715            }
1716
1717            let start_margin = item_borrow_mut.get_layout_start_margin(axis);
1718            item_borrow_mut.set_layout_start_position(
1719                axis,
1720                self.get_start_padding_and_border(axis) + start_margin + offset,
1721                false,
1722            );
1723            let container_dim = self.get_layout_dimension(axis);
1724            let item_dim = item_borrow_mut.get_layout_dimension(axis);
1725            let item_start_pos = item_borrow_mut.get_layout_start_position(axis);
1726            item_borrow_mut.set_layout_end_position(
1727                axis,
1728                container_dim - item_dim - item_start_pos,
1729                false,
1730            );
1731        }
1732    }
1733
1734    pub fn convert_layout_result(&mut self, abs_left: f32, abs_top: f32, scale_factor: f32) {
1735        use crate::util::{double_is_equal, fmod, round_value_to_pixel_grid};
1736
1737        // 转换位置和尺寸值为像素对齐值
1738        // abs_left, abs_top 主要用于考虑父节点的分数偏移的影响
1739        // 例如:如果父节点的分数偏移是 0.3,当前子节点偏移是 0.4,则子节点的绝对偏移是 0.7
1740        // 如果使用 roundf,roundf(0.7) == 1,所以我们需要 abs_left, abs_top 参数
1741
1742        let left = self.layout_result.position[CSSDirection::Left as usize];
1743        let top = self.layout_result.position[CSSDirection::Top as usize];
1744        let width = self.layout_result.dim[Dimension::Width as usize];
1745        let height = self.layout_result.dim[Dimension::Height as usize];
1746
1747        let mut abs_left_new = abs_left + left;
1748        let mut abs_top_new = abs_top + top;
1749        let is_text_node = self.style.node_type == NodeType::Text || self.measure.is_some();
1750
1751        // 转换位置为像素对齐
1752        self.layout_result.position[CSSDirection::Left as usize] =
1753            round_value_to_pixel_grid(left as f64, scale_factor as f64, false, is_text_node) as f32;
1754        self.layout_result.position[CSSDirection::Top as usize] =
1755            round_value_to_pixel_grid(top as f64, scale_factor as f64, false, is_text_node) as f32;
1756
1757        // 检查是否有分数宽度和高度
1758        let width_scaled = width * scale_factor;
1759        let height_scaled = height * scale_factor;
1760        let has_fractional_width = !double_is_equal(fmod(width_scaled, 1.0) as f64, 0.0)
1761            && !double_is_equal(fmod(width_scaled, 1.0) as f64, 1.0);
1762        let has_fractional_height = !double_is_equal(fmod(height_scaled, 1.0) as f64, 0.0)
1763            && !double_is_equal(fmod(height_scaled, 1.0) as f64, 1.0);
1764
1765        let abs_right = abs_left_new + width;
1766        let abs_bottom = abs_top_new + height;
1767
1768        // 转换宽度为像素对齐
1769        let rounded_right = round_value_to_pixel_grid(
1770            abs_right as f64,
1771            scale_factor as f64,
1772            is_text_node && has_fractional_width,
1773            is_text_node && !has_fractional_width,
1774        ) as f32;
1775        let rounded_left = round_value_to_pixel_grid(
1776            abs_left_new as f64,
1777            scale_factor as f64,
1778            false,
1779            is_text_node,
1780        ) as f32;
1781        self.layout_result.dim[Dimension::Width as usize] = rounded_right - rounded_left;
1782
1783        // 转换高度为像素对齐
1784        let rounded_bottom = round_value_to_pixel_grid(
1785            abs_bottom as f64,
1786            scale_factor as f64,
1787            is_text_node && has_fractional_height,
1788            is_text_node && !has_fractional_height,
1789        ) as f32;
1790        let rounded_top =
1791            round_value_to_pixel_grid(abs_top_new as f64, scale_factor as f64, false, is_text_node)
1792                as f32;
1793        self.layout_result.dim[Dimension::Height as usize] = rounded_bottom - rounded_top;
1794
1795        // 递归处理子节点
1796        abs_left_new = rounded_left;
1797        abs_top_new = rounded_top;
1798        for child in self.children.iter() {
1799            child
1800                .borrow_mut()
1801                .convert_layout_result(abs_left_new, abs_top_new, scale_factor);
1802        }
1803    }
1804}