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 }
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 }
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 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}