@@ -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 } ;
1919use tectonic_errors:: prelude:: * ;
2020
2121use crate :: FixedPoint ;
@@ -44,6 +44,10 @@ pub struct FontData {
4444 /// Information about how glyphs can be reverse-mapped to Unicode input
4545 gmap : HashMap < GlyphId , MapEntry > ,
4646
47+ /// The glyph for the basic space character, or zero (typically .notdef) if
48+ /// it can't be found.
49+ space_glyph : GlyphId ,
50+
4751 units_per_em : UfWord ,
4852
4953 hmetrics : Vec < HorizontalMetrics > ,
@@ -184,14 +188,17 @@ impl FontData {
184188
185189 let units_per_em = head. units_per_em ( ) ;
186190
187- // Get the direct mappings.
191+ // Get the direct mappings. While we're at it, figure out the glyph for
192+ // the space character, so that we can know how wide spaces are, so that
193+ // we can guess when to insert spaces into our HTML content.
188194
189195 let cmap = a_ok_or ! (
190196 font. cmap( ) ;
191197 [ "unable to parse OpenType font: missing/invalid CMAP table" ]
192198 ) ;
193199
194200 let mut gmap = HashMap :: new ( ) ;
201+ let mut space_glyph = 0 ;
195202
196203 for usv in valid_usvs ( ) {
197204 let c = char:: from_u32 ( usv) . unwrap ( ) ;
@@ -203,6 +210,10 @@ impl FontData {
203210 }
204211 } ;
205212
213+ if c == ' ' {
214+ space_glyph = gidx;
215+ }
216+
206217 gmap. insert ( gidx, MapEntry :: Direct ( c) ) ;
207218 }
208219
@@ -284,6 +295,7 @@ impl FontData {
284295 basename,
285296 buffer,
286297 gmap,
298+ space_glyph,
287299 units_per_em,
288300 hmetrics,
289301 ascender,
@@ -333,6 +345,17 @@ impl FontData {
333345 } )
334346 }
335347
348+ /// Get the width of the space character as a TeX size.
349+ pub fn space_width ( & self , tex_size : FixedPoint ) -> Option < FixedPoint > {
350+ if self . space_glyph == 0 {
351+ None
352+ } else {
353+ self . hmetrics . get ( self . space_glyph as usize ) . map ( |hm| {
354+ ( hm. advance as f64 * tex_size as f64 / self . units_per_em as f64 ) as FixedPoint
355+ } )
356+ }
357+ }
358+
336359 /// Request that an alternative mapping be allocated for a glyph.
337360 ///
338361 /// The caller must suggest a Unicode character to use for the alternative,
@@ -366,9 +389,11 @@ impl FontData {
366389 * map
367390 }
368391
369- /// Emit customized fonts to the filesystem and compute
370- /// associated CSS for them. Consumes the object.
371- 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 ) > > {
372397 // Write the main font file.
373398
374399 let mut out_path = out_base. to_owned ( ) ;
@@ -378,21 +403,10 @@ impl FontData {
378403 [ "cannot write output file `{}`" , out_path. display( ) ]
379404 ) ;
380405
381- // CSS for the main font.
382- //
383- // We don't atry!() the write because I know that it's to a String,
384- // which can panic but not Err.
406+ // CSS info for the main font.
385407
386408 let rel_url = utf8_percent_encode ( & self . basename , CONTROLS ) . to_string ( ) ;
387-
388- writeln ! (
389- css,
390- r#"@font-face {{
391- font-family: "{}";
392- src: url("{}") format("opentype");
393- }}"# ,
394- base_facename, rel_url
395- ) ?;
409+ let mut rv = vec ! [ ( None , format!( r#"url("{}") format("opentype")"# , rel_url) ) ] ;
396410
397411 // Alternates until we're done
398412
@@ -452,20 +466,15 @@ impl FontData {
452466 // step 5: update CSS
453467
454468 let rel_url = utf8_percent_encode ( & varname, CONTROLS ) . to_string ( ) ;
455-
456- writeln ! (
457- css,
458- r#"@font-face {{
459- font-family: "{}vg{}";
460- src: url("{}") format("opentype");
461- }}"# ,
462- base_facename, cur_map_index, rel_url
463- ) ?;
469+ rv. push ( (
470+ Some ( cur_map_index) ,
471+ format ! ( r#"url("{}") format("opentype")"# , rel_url) ,
472+ ) ) ;
464473 }
465474
466475 // All done!
467476
468- Ok ( ( ) )
477+ Ok ( rv )
469478 }
470479}
471480
0 commit comments