Skip to content

Commit 9bd0983

Browse files
committed
feat(forest): impl external func
1 parent 3400d32 commit 9bd0983

File tree

10 files changed

+513
-407
lines changed

10 files changed

+513
-407
lines changed

float-pigment-forest/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ repository.workspace = true
1212

1313
[lib]
1414
name = "float_pigment_forest"
15-
crate-type = ["staticlib", "cdylib", "rlib"]
15+
crate-type = ["staticlib", "rlib"]
1616

1717
[[bin]]
1818
name = "float_pigment_layout_cpp_binding_gen_tool"
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
use crate::{convert_node_ref_to_ptr, ffi::MeasureMode};
2+
use float_pigment_css::length_num::LengthNum;
3+
use float_pigment_layout::Size;
4+
5+
#[cfg(not(debug_assertions))]
6+
use crate::ffi::{
7+
ExternalDirtyCallback, ExternalGetBaseline, ExternalMeasure, ExternalResolveCalc,
8+
};
9+
10+
use crate::{Len, Node};
11+
12+
#[cfg(debug_assertions)]
13+
use mock_external::{
14+
ExternalDirtyCallback, ExternalGetBaseline, ExternalMeasure, ExternalResolveCalc,
15+
};
16+
17+
fn to_f32_with_max_to_infinity(v: Len) -> f32 {
18+
if v == Len::MAX {
19+
f32::INFINITY
20+
} else {
21+
v.to_f32()
22+
}
23+
}
24+
25+
pub(crate) fn get_baseline_impl(node: &Node, width: Len, height: Len) -> Option<Len> {
26+
#[allow(unused_unsafe)]
27+
unsafe {
28+
let baseline = ExternalGetBaseline(
29+
convert_node_ref_to_ptr(&node) as crate::ffi::NodePtr,
30+
width.to_f32(),
31+
height.to_f32(),
32+
);
33+
Some(Len::from_f32(baseline))
34+
}
35+
}
36+
37+
pub(crate) fn dirty_callback_impl(node: &Node) {
38+
#[allow(unused_unsafe)]
39+
unsafe {
40+
ExternalDirtyCallback(convert_node_ref_to_ptr(&node) as crate::ffi::NodePtr)
41+
};
42+
}
43+
44+
pub(crate) fn measure_impl(
45+
node: &Node,
46+
max_width: Len,
47+
width_mode: MeasureMode,
48+
max_height: Len,
49+
height_mode: MeasureMode,
50+
min_width: Len,
51+
min_height: Len,
52+
max_content_width: Len,
53+
max_content_height: Len,
54+
) -> Option<Size<Len>> {
55+
#[allow(unused_unsafe)]
56+
unsafe {
57+
let size = ExternalMeasure(
58+
convert_node_ref_to_ptr(&node) as crate::ffi::NodePtr,
59+
to_f32_with_max_to_infinity(max_width),
60+
width_mode,
61+
to_f32_with_max_to_infinity(max_height),
62+
height_mode,
63+
min_width.to_f32(),
64+
min_height.to_f32(),
65+
to_f32_with_max_to_infinity(max_content_width),
66+
to_f32_with_max_to_infinity(max_content_height),
67+
);
68+
Some(Size::new(
69+
Len::from_f32(size.width),
70+
Len::from_f32(size.height),
71+
))
72+
}
73+
}
74+
75+
pub(crate) fn resolve_calc_impl(node: &Node, calc_handle: i32, owner: Len) -> Len {
76+
#[allow(unused_unsafe)]
77+
unsafe {
78+
Len::from_f32(ExternalResolveCalc(
79+
convert_node_ref_to_ptr(&node) as crate::ffi::NodePtr,
80+
calc_handle,
81+
owner.to_f32(),
82+
))
83+
}
84+
}
85+
86+
#[cfg(debug_assertions)]
87+
pub mod mock_external {
88+
89+
#[derive(Debug, Default, Clone)]
90+
pub struct TextInfo {
91+
pub(crate) font_size: f32,
92+
// raw_text: String
93+
pub(crate) text_len: usize,
94+
}
95+
96+
impl TextInfo {
97+
pub(crate) fn measure(
98+
&self,
99+
min_width: f32,
100+
min_height: f32,
101+
max_width: f32,
102+
max_height: f32,
103+
max_content_width: f32,
104+
max_content_height: f32,
105+
) -> (f32, f32) {
106+
let text_len = self.text_len;
107+
let text_width = self.font_size * text_len as f32;
108+
let max_w = max_width.min(max_content_width);
109+
let max_h = max_height.min(max_content_height);
110+
let measured_width;
111+
let measured_height;
112+
if text_width <= max_w {
113+
// single line
114+
measured_width = text_width;
115+
measured_height = self.font_size;
116+
} else {
117+
// multi line
118+
let mut row_count = (max_w.to_f32() / self.font_size).floor();
119+
if row_count < 1. {
120+
row_count = 1.;
121+
}
122+
let col_count = (text_len as f32 / row_count).ceil();
123+
measured_width = (row_count * self.font_size) as i32 as f32;
124+
measured_height = (col_count * self.font_size) as i32 as f32;
125+
}
126+
println!(
127+
"text_info: {:?}, width: {:?} ~ {:?}, height: {:?} ~ {:?}, max_content_width: {:?}, max_content_height: {:?}, measured_width: {:?}, measured_height: {:?}",
128+
self,
129+
min_width,
130+
max_width,
131+
min_height,
132+
max_height,
133+
max_content_width,
134+
max_content_height,
135+
measured_width,
136+
measured_height,
137+
);
138+
(measured_width, measured_height.min(max_h))
139+
}
140+
}
141+
142+
pub struct TextInfoBuilder(TextInfo);
143+
144+
impl TextInfoBuilder {
145+
pub fn new() -> Self {
146+
Self(TextInfo {
147+
font_size: 16.,
148+
// raw_text: String::new(),
149+
text_len: 0,
150+
})
151+
}
152+
pub fn with_text_len(mut self, text_len: usize) -> Self {
153+
self.0.text_len = text_len;
154+
self
155+
}
156+
pub fn with_font_size(mut self, font_size: f32) -> Self {
157+
self.0.font_size = font_size;
158+
self
159+
}
160+
pub fn set_font_size(&mut self, font_size: f32) {
161+
self.0.font_size = font_size;
162+
}
163+
pub fn build(self) -> TextInfo {
164+
self.0
165+
}
166+
}
167+
use std::{cell::RefCell, collections::HashMap};
168+
169+
use float_pigment_css::length_num::LengthNum;
170+
171+
use crate::{ffi::MeasureMode, get_ref_from_node_ptr, Node, NodePtr};
172+
173+
pub enum MeasureType {
174+
Text(TextInfo),
175+
SpecifiedSize((f32, f32)),
176+
Custom(
177+
Box<
178+
dyn Fn(&Node, f32, MeasureMode, f32, MeasureMode, f32, f32, f32, f32) -> (f32, f32),
179+
>,
180+
),
181+
}
182+
183+
thread_local! {
184+
static COLLECTION: RefCell<HashMap<*mut Node, MeasureType>> = RefCell::new(HashMap::new());
185+
}
186+
187+
pub fn set_node_measure_type(node: *mut Node, measure_type: MeasureType) {
188+
COLLECTION.with(|collection| {
189+
let mut collection = collection.borrow_mut();
190+
collection.insert(node, measure_type);
191+
});
192+
}
193+
194+
#[allow(non_snake_case)]
195+
pub(crate) fn ExternalGetBaseline(_node: *mut (), _width: f32, height: f32) -> f32 {
196+
let mut res = 0.;
197+
COLLECTION.with(|collection| {
198+
let collection = collection.borrow();
199+
if let Some(measure_type) = collection.get(&(_node as *mut Node)) {
200+
match measure_type {
201+
MeasureType::Text(text_info) => {
202+
res = text_info.font_size;
203+
}
204+
_ => res = height,
205+
}
206+
}
207+
});
208+
res
209+
}
210+
211+
#[allow(non_snake_case)]
212+
pub(crate) fn ExternalMeasure(
213+
node: *mut (),
214+
max_width: f32,
215+
_width_mode: MeasureMode,
216+
max_height: f32,
217+
_height_mode: MeasureMode,
218+
min_width: f32,
219+
min_height: f32,
220+
max_content_width: f32,
221+
max_content_height: f32,
222+
) -> crate::ffi::Size {
223+
let mut res = crate::ffi::Size {
224+
width: 0.,
225+
height: 0.,
226+
};
227+
COLLECTION.with(|collection| {
228+
let collection = collection.borrow();
229+
if let Some(measure_type) = collection.get(&(node as *mut Node)) {
230+
match measure_type {
231+
MeasureType::Text(text_info) => {
232+
let (width, height) = text_info.measure(
233+
min_width,
234+
min_height,
235+
max_width,
236+
max_height,
237+
max_content_width,
238+
max_content_height,
239+
);
240+
res = crate::ffi::Size {
241+
width: width,
242+
height: height,
243+
};
244+
}
245+
MeasureType::SpecifiedSize((width, height)) => {
246+
res = crate::ffi::Size {
247+
width: *width,
248+
height: *height,
249+
};
250+
}
251+
MeasureType::Custom(func) => {
252+
let (width, height) = func(
253+
unsafe { get_ref_from_node_ptr(node as NodePtr) },
254+
max_width,
255+
_width_mode,
256+
max_height,
257+
_height_mode,
258+
min_width,
259+
min_height,
260+
max_content_width,
261+
max_content_height,
262+
);
263+
res = crate::ffi::Size { width, height }
264+
}
265+
}
266+
}
267+
});
268+
res
269+
}
270+
271+
#[allow(non_snake_case)]
272+
pub(crate) fn ExternalResolveCalc(_node: *mut (), _calc_handle: i32, _owner: f32) -> f32 {
273+
todo!()
274+
}
275+
276+
#[allow(non_snake_case)]
277+
pub(crate) fn ExternalDirtyCallback(node: *mut ()) {
278+
use crate::DumpNode;
279+
println!("trigger dirty callback of Node: {}", unsafe {
280+
get_ref_from_node_ptr(node as *mut Node).dump_to_html(
281+
crate::DumpOptions {
282+
recursive: false,
283+
layout: true,
284+
style: crate::DumpStyleMode::None,
285+
},
286+
0,
287+
)
288+
});
289+
}
290+
}

0 commit comments

Comments
 (0)