Skip to content

Commit ce1e76e

Browse files
committed
engine_spx2html: tidy up font family naming and grouping
1 parent 9906d5b commit ce1e76e

2 files changed

Lines changed: 132 additions & 45 deletions

File tree

crates/engine_spx2html/src/font.rs

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use pinot::{
1515
types::{FWord, Tag, UfWord},
1616
FontDataRef, TableProvider,
1717
};
18-
use std::{collections::HashMap, fmt::Write, num::Wrapping, path::Path};
18+
use std::{collections::HashMap, num::Wrapping, path::Path};
1919
use tectonic_errors::prelude::*;
2020

2121
use crate::FixedPoint;
@@ -389,9 +389,11 @@ impl FontData {
389389
*map
390390
}
391391

392-
/// Emit customized fonts to the filesystem and compute
393-
/// associated CSS for them. Consumes the object.
394-
pub fn emit<W: Write>(self, out_base: &Path, base_facename: &str, mut css: W) -> Result<()> {
392+
/// Emit customized fonts to the filesystem and return information so that
393+
/// appropriate CSS can be generated. Consumes the object.
394+
///
395+
/// Return value is a vec of (alternate-map-index, CSS-src-field).
396+
pub fn emit(self, out_base: &Path) -> Result<Vec<(Option<usize>, String)>> {
395397
// Write the main font file.
396398

397399
let mut out_path = out_base.to_owned();
@@ -401,21 +403,10 @@ impl FontData {
401403
["cannot write output file `{}`", out_path.display()]
402404
);
403405

404-
// CSS for the main font.
405-
//
406-
// We don't atry!() the write because I know that it's to a String,
407-
// which can panic but not Err.
406+
// CSS info for the main font.
408407

409408
let rel_url = utf8_percent_encode(&self.basename, CONTROLS).to_string();
410-
411-
writeln!(
412-
css,
413-
r#"@font-face {{
414-
font-family: "{}";
415-
src: url("{}") format("opentype");
416-
}}"#,
417-
base_facename, rel_url
418-
)?;
409+
let mut rv = vec![(None, format!(r#"url("{}") format("opentype")"#, rel_url))];
419410

420411
// Alternates until we're done
421412

@@ -475,20 +466,15 @@ impl FontData {
475466
// step 5: update CSS
476467

477468
let rel_url = utf8_percent_encode(&varname, CONTROLS).to_string();
478-
479-
writeln!(
480-
css,
481-
r#"@font-face {{
482-
font-family: "{}vg{}";
483-
src: url("{}") format("opentype");
484-
}}"#,
485-
base_facename, cur_map_index, rel_url
486-
)?;
469+
rv.push((
470+
Some(cur_map_index),
471+
format!(r#"url("{}") format("opentype")"#, rel_url),
472+
));
487473
}
488474

489475
// All done!
490476

491-
Ok(())
477+
Ok(rv)
492478
}
493479
}
494480

crates/engine_spx2html/src/lib.rs

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@ impl InitializationState {
363363

364364
let info = FontInfo {
365365
rel_url: utf8_percent_encode(basename, CONTROLS).to_string(),
366+
family_name: format!("tdux{}", font_num),
367+
family_relation: FamilyRelativeFontId::Regular,
366368
fd_key,
367369
size,
368370
face_index,
@@ -457,6 +459,7 @@ impl InitializationState {
457459

458460
fn handle_end_define_font_family(&mut self, common: &mut Common) -> Result<()> {
459461
if let Some(b) = self.cur_font_family_definition.take() {
462+
let family_name = b.family_name;
460463
let regular = a_ok_or!(b.regular; ["no regular face defined"]);
461464
let bold = a_ok_or!(b.bold; ["no bold face defined"]);
462465
let italic = a_ok_or!(b.italic; ["no italic face defined"]);
@@ -471,6 +474,29 @@ impl InitializationState {
471474
bold_italic,
472475
},
473476
);
477+
478+
// Now update the info records for the relevant fonts to capture the
479+
// established relationship.
480+
481+
if let Some(info) = self.fonts.get_mut(&regular) {
482+
info.family_name = family_name.clone();
483+
info.family_relation = FamilyRelativeFontId::Regular;
484+
}
485+
486+
if let Some(info) = self.fonts.get_mut(&bold) {
487+
info.family_name = family_name.clone();
488+
info.family_relation = FamilyRelativeFontId::Bold;
489+
}
490+
491+
if let Some(info) = self.fonts.get_mut(&italic) {
492+
info.family_name = family_name.clone();
493+
info.family_relation = FamilyRelativeFontId::Italic;
494+
}
495+
496+
if let Some(info) = self.fonts.get_mut(&bold_italic) {
497+
info.family_name = family_name.clone();
498+
info.family_relation = FamilyRelativeFontId::BoldItalic;
499+
}
474500
} else {
475501
tt_warning!(
476502
common.status,
@@ -527,6 +553,11 @@ impl InitializationState {
527553
b.italic = Some(font_num);
528554
} else {
529555
b.regular = Some(font_num);
556+
b.family_name = if let Some(fname) = text.strip_prefix("family-name:") {
557+
fname.to_owned()
558+
} else {
559+
format!("tdux{}", font_num)
560+
};
530561

531562
// Say that the "regular" font of the first font family definition
532563
// is the main body font.
@@ -559,10 +590,6 @@ impl InitializationState {
559590

560591
let rems_per_tex = if let Some(fnum) = self.main_body_font_num {
561592
let info = self.fonts.get(&fnum).unwrap();
562-
563-
// Make sure this stays synced with the CSS emitted below.
564-
context.insert("tduxMainBodyFontFamily", &format!("tdux{}", info.fd_key));
565-
566593
1.0 / (info.size as f32)
567594
} else {
568595
1. / 65536.
@@ -1541,8 +1568,9 @@ impl EmittingState {
15411568

15421569
write!(
15431570
self.current_content,
1544-
"<span style=\"font-size: {}rem; font-family: tdux{}\">",
1545-
rel_size, fi.fd_key,
1571+
"<span style=\"font-size: {}rem; {}\">",
1572+
rel_size,
1573+
fi.selection_style_text(None)
15461574
)
15471575
.unwrap();
15481576

@@ -1645,14 +1673,16 @@ impl EmittingState {
16451673
MapEntry::MathGrowingVariant(c, _, _) => (c, true),
16461674
};
16471675

1648-
let font_fam = if need_alt {
1676+
let alt_index = if need_alt {
16491677
let map = fd.request_alternative(gi.glyph, ch);
16501678
ch = map.usv;
1651-
format!("tdux{}vg{}", fi.fd_key, map.alternate_map_index)
1679+
Some(map.alternate_map_index)
16521680
} else {
1653-
format!("tdux{}", fi.fd_key)
1681+
None
16541682
};
16551683

1684+
let font_sel = fi.selection_style_text(alt_index);
1685+
16561686
// dy gives the target position of this glyph's baseline
16571687
// relative to the canvas's baseline. For our `position:
16581688
// absolute` layout, we have to convert that into the distance
@@ -1685,11 +1715,11 @@ impl EmittingState {
16851715

16861716
write!(
16871717
inner_content,
1688-
"<span class=\"ci\" style=\"top: {}rem; left: {}rem; font-size: {}rem; font-family: {}\">",
1718+
"<span class=\"ci\" style=\"top: {}rem; left: {}rem; font-size: {}rem; {}\">",
16891719
top_rem,
16901720
gi.dx as f32 * self.rems_per_tex,
16911721
rel_size,
1692-
font_fam,
1722+
font_sel,
16931723
)
16941724
.unwrap();
16951725
html_escape::encode_text_to_string(ch_as_str, &mut inner_content);
@@ -1839,14 +1869,33 @@ impl EmittingState {
18391869

18401870
// The reason we're doing all this: we can now emit our customized font
18411871
// files that provide access to glyphs that we can't get the browser to
1842-
// display directly. One of the emitted keys should match
1843-
// tduxMainBodyFontFamily defined at the end of the initialization
1844-
// stage.
1872+
// display directly. First, emit the font files via the font data.
18451873

1846-
let mut faces = String::default();
1874+
let mut emitted_info = HashMap::new();
18471875

18481876
for (fd_key, data) in self.font_data.drain() {
1849-
data.emit(common.out_base, &format!("tdux{}", fd_key), &mut faces)?;
1877+
let emi = data.emit(common.out_base)?;
1878+
emitted_info.insert(fd_key, emi);
1879+
}
1880+
1881+
// Now we can generate the CSS.
1882+
1883+
let mut faces = String::default();
1884+
1885+
for fi in self.fonts.values() {
1886+
let emi = emitted_info.get(&fi.fd_key).unwrap();
1887+
1888+
for (alt_index, css_src) in emi {
1889+
let _ignored = writeln!(
1890+
faces,
1891+
r#"@font-face {{
1892+
{}
1893+
src: {};
1894+
}}"#,
1895+
fi.font_face_text(*alt_index),
1896+
css_src,
1897+
);
1898+
}
18501899
}
18511900

18521901
self.context.insert("tduxFontFaces", &faces);
@@ -1863,8 +1912,22 @@ type FontNum = i32;
18631912
#[allow(dead_code)]
18641913
#[derive(Debug)]
18651914
struct FontInfo {
1915+
/// Relative URL to the font data file
18661916
rel_url: String,
1917+
1918+
/// CSS name of the font family with which this font is associated;
1919+
/// autogenerated if not specified during initialization.
1920+
family_name: String,
1921+
1922+
/// This font's "relationship" to its family. Defaults to Regular to
1923+
/// if it's not associated with a full-fledged family.
1924+
family_relation: FamilyRelativeFontId,
1925+
1926+
/// Integer key used to relate this TeX font to its FontData. Multiple
1927+
/// fonts may use the same FontData, if they refer to the same backing
1928+
/// file.
18671929
fd_key: usize,
1930+
18681931
size: FixedPoint,
18691932
face_index: u32,
18701933
color_rgba: Option<u32>,
@@ -1873,7 +1936,44 @@ struct FontInfo {
18731936
embolden: Option<u32>,
18741937
}
18751938

1876-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1939+
impl FontInfo {
1940+
fn selection_style_text(&self, alternate_map_index: Option<usize>) -> String {
1941+
let alt_text = alternate_map_index
1942+
.map(|i| format!("vg{}", i))
1943+
.unwrap_or_default();
1944+
1945+
let extra = match self.family_relation {
1946+
FamilyRelativeFontId::Regular => "",
1947+
FamilyRelativeFontId::Bold => "; font-weight: bold",
1948+
FamilyRelativeFontId::Italic => "; font-style: italic",
1949+
FamilyRelativeFontId::BoldItalic => "; font-weight: bold; font-style: italic",
1950+
FamilyRelativeFontId::Other(_) => unreachable!(),
1951+
};
1952+
1953+
format!("font-family: {}{}{}", self.family_name, alt_text, extra)
1954+
}
1955+
1956+
fn font_face_text(&self, alternate_map_index: Option<usize>) -> String {
1957+
let alt_text = alternate_map_index
1958+
.map(|i| format!("vg{}", i))
1959+
.unwrap_or_default();
1960+
1961+
let extra = match self.family_relation {
1962+
FamilyRelativeFontId::Regular => "",
1963+
FamilyRelativeFontId::Bold => "\n font-weight: bold;",
1964+
FamilyRelativeFontId::Italic => "\n font-style: italic;",
1965+
FamilyRelativeFontId::BoldItalic => "\n font-weight: bold;\n font-style: italic;",
1966+
FamilyRelativeFontId::Other(_) => unreachable!(),
1967+
};
1968+
1969+
format!(
1970+
r#"font-family: "{}{}";{}"#,
1971+
self.family_name, alt_text, extra
1972+
)
1973+
}
1974+
}
1975+
1976+
#[derive(Clone, Debug, Eq, PartialEq)]
18771977
struct FontFamily {
18781978
regular: FontNum,
18791979
bold: FontNum,
@@ -2023,6 +2123,7 @@ struct PathToNewFont {
20232123

20242124
#[derive(Debug, Default)]
20252125
struct FontFamilyBuilder {
2126+
family_name: String,
20262127
regular: Option<FontNum>,
20272128
bold: Option<FontNum>,
20282129
italic: Option<FontNum>,
@@ -2031,7 +2132,7 @@ struct FontFamilyBuilder {
20312132

20322133
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20332134
enum FamilyRelativeFontId {
2034-
/// This font is the regular font of the current family
2135+
/// This font is the regular font of the current family.
20352136
Regular,
20362137

20372138
/// This font is the bold font of the current family.

0 commit comments

Comments
 (0)