fix(web): measure canvas text with draw style
This commit is contained in:
parent
242031c9b2
commit
a9a7d33c2d
|
|
@ -212,6 +212,8 @@ extern "C" {
|
|||
);
|
||||
#[wasm_bindgen(method, js_name = measureText)]
|
||||
fn measure_text(this: &OpCk, t: &str, sz: f32) -> f32;
|
||||
#[wasm_bindgen(method, js_name = measureTextStyled)]
|
||||
fn measure_text_styled(this: &OpCk, t: &str, sz: f32, weight: i32, italic: bool) -> f32;
|
||||
#[wasm_bindgen(method, js_name = registerSystemFont)]
|
||||
fn register_system_font(this: &OpCk, family: &str, bytes: &[u8]) -> bool;
|
||||
#[wasm_bindgen(method, js_name = clipRect)]
|
||||
|
|
@ -541,10 +543,21 @@ impl RenderBackend for CanvasKitBackend {
|
|||
}
|
||||
}
|
||||
fn measure_text(&mut self, text: &str, font_size: f32) -> f32 {
|
||||
self.ck.measure_text(text, font_size)
|
||||
self.ck.measure_text_styled(text, font_size, 400, false)
|
||||
}
|
||||
fn measure_text_weighted(&mut self, text: &str, font_size: f32, _weight: u16) -> f32 {
|
||||
self.ck.measure_text(text, font_size)
|
||||
fn measure_text_weighted(&mut self, text: &str, font_size: f32, weight: u16) -> f32 {
|
||||
self.ck
|
||||
.measure_text_styled(text, font_size, i32::from(weight), false)
|
||||
}
|
||||
fn measure_text_styled(
|
||||
&mut self,
|
||||
text: &str,
|
||||
font_size: f32,
|
||||
weight: u16,
|
||||
italic: bool,
|
||||
) -> f32 {
|
||||
self.ck
|
||||
.measure_text_styled(text, font_size, weight as i32, italic)
|
||||
}
|
||||
|
||||
fn clip_rect(&mut self, rect: Rect) {
|
||||
|
|
|
|||
|
|
@ -396,13 +396,17 @@ export async function opCkInit(canvasId) {
|
|||
p.delete();
|
||||
},
|
||||
measureText(t, sz) {
|
||||
return this.measureTextStyled(t, sz, 400, false);
|
||||
},
|
||||
measureTextStyled(t, sz, weight, italic) {
|
||||
let w = 0;
|
||||
for (const seg of segments(t)) {
|
||||
if (shouldUseBrowserTextFallback(seg.text, seg.emoji)) {
|
||||
w += browserTextMeasure(seg.text, sz);
|
||||
w += browserTextMeasure(seg.text, sz, weight, italic);
|
||||
continue;
|
||||
}
|
||||
const f = new CK.Font(tfFor(seg.text, seg.emoji), sz);
|
||||
if (italic && !seg.emoji) f.setSkewX(-0.25);
|
||||
w += runWidth(f, seg.text);
|
||||
f.delete();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ fn canvaskit_text_defaults_to_browser_system_font_fallback() {
|
|||
"const segments = (t)",
|
||||
"const shouldUseBrowserTextFallback = (_t, _emojiRun) => Boolean(browserTextCtx);",
|
||||
"drawBrowserText(seg.text, cx, y, sz, weight, italic, r, g, b, a)",
|
||||
"browserTextMeasure(seg.text, sz)",
|
||||
"browserTextMeasure(seg.text, sz, weight, italic)",
|
||||
"CK.Typeface.GetDefault()",
|
||||
] {
|
||||
assert!(
|
||||
|
|
@ -177,6 +177,40 @@ fn canvaskit_browser_text_fallback_does_not_require_canvas_paint() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canvaskit_text_measurement_uses_draw_text_style() {
|
||||
let bridge = std::fs::read_to_string(format!(
|
||||
"{}/src/op_ck_bridge.js",
|
||||
env!("CARGO_MANIFEST_DIR")
|
||||
))
|
||||
.expect("CanvasKit bridge source is readable");
|
||||
let backend =
|
||||
std::fs::read_to_string(format!("{}/src/canvaskit.rs", env!("CARGO_MANIFEST_DIR")))
|
||||
.expect("CanvasKit backend source is readable");
|
||||
|
||||
for marker in [
|
||||
"measureTextStyled(t, sz, weight, italic)",
|
||||
"browserTextMeasure(seg.text, sz, weight, italic)",
|
||||
] {
|
||||
assert!(
|
||||
bridge.contains(marker),
|
||||
"CanvasKit bridge must preserve `{marker}` so measured text matches drawn text"
|
||||
);
|
||||
}
|
||||
|
||||
for marker in [
|
||||
"fn measure_text_styled(",
|
||||
"weight: u16,",
|
||||
"italic: bool,",
|
||||
".measure_text_styled(text, font_size, weight as i32, italic)",
|
||||
] {
|
||||
assert!(
|
||||
backend.contains(marker),
|
||||
"CanvasKit backend must preserve `{marker}` so web layout measures with draw-time text style"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canvaskit_paint_style_is_guarded_before_set_style() {
|
||||
let source = std::fs::read_to_string(format!(
|
||||
|
|
@ -243,7 +277,7 @@ fn canvaskit_bridge_uses_browser_text_fallback_when_local_font_api_is_unavailabl
|
|||
"const shouldUseBrowserTextFallback",
|
||||
"const drawBrowserText",
|
||||
"CK.MakeImageFromCanvasImageSource",
|
||||
"browserTextMeasure(seg.text, sz)",
|
||||
"browserTextMeasure(seg.text, sz, weight, italic)",
|
||||
] {
|
||||
assert!(
|
||||
source.contains(marker),
|
||||
|
|
|
|||
Loading…
Reference in a new issue