1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt};
use crate::flow::BlockFormattingContext;
use crate::fragments::Fragment;
use crate::positioned::PositioningContext;
use crate::replaced::ReplacedContent;
use crate::sizing::{BoxContentSizes, ContentSizesRequest};
use crate::style_ext::DisplayInside;
use crate::ContainingBlock;
use servo_arc::Arc;
use std::convert::TryInto;
use style::dom::OpaqueNode;
use style::properties::ComputedValues;
use style::values::computed::Length;
/// https://drafts.csswg.org/css-display/#independent-formatting-context
#[derive(Debug)]
pub(crate) struct IndependentFormattingContext {
pub tag: OpaqueNode,
pub style: Arc<ComputedValues>,
/// If it was requested during construction
pub content_sizes: BoxContentSizes,
contents: IndependentFormattingContextContents,
}
pub(crate) struct IndependentLayout {
pub fragments: Vec<Fragment>,
/// https://drafts.csswg.org/css2/visudet.html#root-height
pub content_block_size: Length,
}
// Private so that code outside of this module cannot match variants.
// It should got through methods instead.
#[derive(Debug)]
enum IndependentFormattingContextContents {
Flow(BlockFormattingContext),
// Not called FC in specs, but behaves close enough
Replaced(ReplacedContent),
// Other layout modes go here
}
pub(crate) struct NonReplacedIFC<'a>(NonReplacedIFCKind<'a>);
enum NonReplacedIFCKind<'a> {
Flow(&'a BlockFormattingContext),
}
impl IndependentFormattingContext {
pub fn construct<'dom>(
context: &LayoutContext,
node: impl NodeExt<'dom>,
style: Arc<ComputedValues>,
display_inside: DisplayInside,
contents: Contents,
content_sizes: ContentSizesRequest,
) -> Self {
match contents.try_into() {
Ok(non_replaced) => match display_inside {
DisplayInside::Flow | DisplayInside::FlowRoot => {
let (bfc, content_sizes) = BlockFormattingContext::construct(
context,
node,
&style,
non_replaced,
content_sizes,
);
Self {
tag: node.as_opaque(),
style,
content_sizes,
contents: IndependentFormattingContextContents::Flow(bfc),
}
},
},
Err(replaced) => {
let content_sizes = content_sizes.compute(|| replaced.inline_content_sizes(&style));
Self {
tag: node.as_opaque(),
style,
content_sizes,
contents: IndependentFormattingContextContents::Replaced(replaced),
}
},
}
}
pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> {
use self::IndependentFormattingContextContents as Contents;
use self::NonReplacedIFC as NR;
use self::NonReplacedIFCKind as Kind;
match &self.contents {
Contents::Replaced(r) => Ok(r),
Contents::Flow(f) => Err(NR(Kind::Flow(f))),
}
}
}
impl<'a> NonReplacedIFC<'a> {
pub fn layout(
&self,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext<'a>,
containing_block: &ContainingBlock,
tree_rank: usize,
) -> IndependentLayout {
match &self.0 {
NonReplacedIFCKind::Flow(bfc) => bfc.layout(
layout_context,
positioning_context,
containing_block,
tree_rank,
),
}
}
}
|