Skip to content

Commit ad031bf

Browse files
committed
Detect whether the browser Canvas API supports font features
Not all current browsers seem to support the configuration of font features as done in 76fa280, for example it fails in Chrome v108 or Edge v107 on Windows. Implement a work-around by testing the font after it has been loaded regarding the measured width of numeric glyphs and load a replacement font when necessary. The replacement font file is a patched variant of Overpass v4.0 where the default Unicode entries for digit zero to nine have been changed to the '.tf' glyph variants.
1 parent 66e58b5 commit ad031bf

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ features = [
6060
'Storage',
6161
'SvgElement',
6262
'Text',
63+
'TextMetrics',
6364
'Window',
6465
]
6566

src/view/export.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,13 +378,52 @@ impl ExportView {
378378
document.fonts().add(&title_font)?;
379379
let _ = title_font.load();
380380

381+
// Not all browser + operating system combinations have support for enabling the tabular
382+
// number glyph variants by using FontFace::set_feature_settings(). If such support is
383+
// available it saves us from downloading an extra font file for tile labels, so we
384+
// auto-detect browser support.
385+
let font_load_cb = Closure::wrap(Box::new({
386+
let canvas = canvas.clone();
387+
move |font: JsValue| {
388+
389+
let context = check!(canvas.get_context("2d").ok().flatten()
390+
.and_then(|obj| obj.dyn_into::<web_sys::CanvasRenderingContext2d>().ok()));
391+
context.save();
392+
context.set_font("bold 16px OverpassTnum, sans-serif");
393+
let width_str0 = check!(context.measure_text("0000").ok()).width();
394+
let width_str1 = check!(context.measure_text("1111").ok()).width();
395+
debug!("label font width 0/1: {:.3}/{:.3}, ratio: {:.3}",
396+
width_str0, width_str1, width_str0 / width_str1);
397+
context.restore();
398+
399+
// compare widths of both numerical sample strings, trigger
400+
// load of a replacement font if they differ by more than 20%
401+
if (width_str0 - width_str1).abs() > 0.2 * width_str0 {
402+
warn!("Detected missing support for font settings configuration in the Canvas API of this browser. Loading a replacement font instead.");
403+
404+
let document = canvas.owner_document().unwrap();
405+
let font = check!(font.dyn_into::<FontFace>().ok());
406+
document.fonts().delete(&font);
407+
408+
let label_font = check!(FontFace::new_with_str("OverpassTnum",
409+
"url('overpass+tnum-bold.woff2') format('woff2')").ok());
410+
label_font.set_style("normal");
411+
label_font.set_weight("bold");
412+
check!(document.fonts().add(&label_font).ok());
413+
let _ = label_font.load();
414+
}
415+
}
416+
}) as Box<dyn FnMut(_)>);
417+
381418
let label_font = FontFace::new_with_str("OverpassTnum",
382419
"url('overpass-bold.woff2') format('woff2')")?;
383420
label_font.set_style("normal");
384421
label_font.set_weight("bold");
385422
label_font.set_feature_settings("\"tnum\" on");
386423
document.fonts().add(&label_font)?;
387-
let _ = label_font.load();
424+
let _ = label_font.load()?
425+
.then(&font_load_cb);
426+
font_load_cb.forget();
388427

389428
Ok(ExportView {
390429
base_layout, export_layout, export_scale, map, tile_labels_visible,

www/overpass+tnum-bold.woff2

81.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)