Skip to content

Commit 243a1e6

Browse files
committed
estimate text layout using an offscreen canvas
1 parent 3ad52da commit 243a1e6

File tree

2 files changed

+41
-27
lines changed

2 files changed

+41
-27
lines changed

plotters/Cargo.toml

+20-13
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,33 @@ version = "0.2.89"
5858
[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies.web-sys]
5959
version = "0.3.66"
6060
features = [
61-
"Document",
62-
"DomRect",
63-
"Element",
64-
"HtmlElement",
65-
"Node",
66-
"Window",
67-
"HtmlCanvasElement",
68-
"CanvasRenderingContext2d",
61+
"Document",
62+
"DomRect",
63+
"Element",
64+
"HtmlElement",
65+
"Node",
66+
"Window",
67+
"HtmlCanvasElement",
68+
"CanvasRenderingContext2d",
69+
"OffscreenCanvas",
70+
"OffscreenCanvasRenderingContext2d",
71+
"TextMetrics",
6972
]
7073

7174
[features]
7275
default = [
73-
"bitmap_backend", "bitmap_encoder", "bitmap_gif",
76+
"bitmap_backend",
77+
"bitmap_encoder",
78+
"bitmap_gif",
7479
"svg_backend",
7580
"chrono",
7681
"ttf",
7782
"image",
78-
"deprecated_items", "all_series", "all_elements",
83+
"deprecated_items",
84+
"all_series",
85+
"all_elements",
7986
"full_palette",
80-
"colormaps"
87+
"colormaps",
8188
]
8289
all_series = ["area_series", "line_series", "point_series", "surface_series"]
8390
all_elements = ["errorbar", "candlestick", "boxplot", "histogram"]
@@ -117,7 +124,8 @@ datetime = ["chrono"]
117124
serialization = ["serde"]
118125
evcxr = ["svg_backend"]
119126
evcxr_bitmap = ["evcxr", "bitmap_backend", "plotters-svg/bitmap_encoder"]
120-
deprecated_items = [] # Keep some of the deprecated items for backward compatibility
127+
deprecated_items = [
128+
] # Keep some of the deprecated items for backward compatibility
121129

122130
[dev-dependencies]
123131
itertools = "0.10.0"
@@ -143,4 +151,3 @@ path = "benches/main.rs"
143151
[package.metadata.docs.rs]
144152
all-features = true
145153
rustdoc-args = ["--cfg", "doc_cfg"]
146-

plotters/src/style/font/web.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{FontData, FontFamily, FontStyle, LayoutBox};
22
use wasm_bindgen::JsCast;
3-
use web_sys::{window, HtmlElement};
3+
use web_sys::{window, HtmlElement, OffscreenCanvas, OffscreenCanvasRenderingContext2d};
44

55
#[derive(Debug, Clone)]
66
pub enum FontError {
@@ -29,18 +29,25 @@ impl FontData for FontDataInternal {
2929
))
3030
}
3131
fn estimate_layout(&self, size: f64, text: &str) -> Result<LayoutBox, Self::ErrorType> {
32-
let window = window().unwrap();
33-
let document = window.document().unwrap();
34-
let body = document.body().unwrap();
35-
let span = document.create_element("span").unwrap();
36-
span.set_text_content(Some(text));
37-
span.set_attribute("style", &format!("display: inline-block; font-family:{}; font-style:{}; font-size: {}px; position: fixed; top: 100%", self.0, self.1, size)).unwrap();
38-
let span = span.into();
39-
body.append_with_node_1(&span).unwrap();
40-
let elem = JsCast::dyn_into::<HtmlElement>(span).unwrap();
41-
let height = elem.offset_height() as i32;
42-
let width = elem.offset_width() as i32;
43-
elem.remove();
44-
Ok(((0, 0), (width, height)))
32+
let canvas = OffscreenCanvas::new(0, 0).expect("offscreen canvas");
33+
let context = canvas
34+
.get_context("2d")
35+
.expect("getContext")
36+
.expect("context for 2d not null")
37+
.dyn_into::<OffscreenCanvasRenderingContext2d>()
38+
.expect("cast");
39+
context.set_font("sans-serif");
40+
context.set_font(&format!(
41+
"{} {}px {}",
42+
self.1.as_str(),
43+
size,
44+
self.0.as_str(),
45+
));
46+
let metrics = context
47+
.measure_text(text)
48+
.expect("measure_text to return metrics");
49+
let width = metrics.width();
50+
let height = metrics.font_bounding_box_ascent() + metrics.font_bounding_box_descent();
51+
Ok(((0, 0), (width as i32, height as i32)))
4552
}
4653
}

0 commit comments

Comments
 (0)