@@ -48,32 +48,19 @@ pub(crate) mod skrifa {
4848 }
4949
5050 impl < ' a > SkrifaInterjector < ' a > {
51- /// Return the advance width and left side bearing of the glyph.
52- pub ( crate ) fn horizontal_metrics ( & self , glyph : u16 ) -> Option < ( u16 , i16 ) > {
53- let metrics = self . font_ref . glyph_metrics ( Size :: unscaled ( ) , & self . location ) ;
54-
55- let adv = metrics. advance_width ( GlyphId :: new ( glyph as u32 ) ) ?;
56- // Note that for variable fonts, our left side bearing points don't seem to
57- // match the ones from fonttools (they use some different technique for deriving
58- // it which isn't reflected in skrifa's API), but I _think_ that this shouldn't
59- // really be relevant in the context of PDF.
60- let lsb = metrics. left_side_bearing ( GlyphId :: new ( glyph as u32 ) ) ?;
61-
62- Some ( ( adv. round ( ) as u16 , lsb. round ( ) as i16 ) )
63- }
64-
6551 /// Return the glyph description in the `glyf` outline format.
66- pub ( crate ) fn glyph_data < ' b > (
52+ pub ( crate ) fn interject < ' b > (
6753 & ' b self ,
6854 maxp_data : & ' b mut MaxpData ,
6955 glyph : u16 ,
70- ) -> Option < Vec < u8 > > {
56+ ) -> Option < ( u16 , i16 , Vec < u8 > ) > {
7157 let outlines = self . font_ref . outline_glyphs ( ) ;
58+ let metrics = self . font_ref . glyph_metrics ( Size :: unscaled ( ) , & self . location ) ;
7259
7360 let mut outline_builder = OutlinePath :: new ( ) ;
74- let glyph = GlyphId :: new ( glyph as u32 ) ;
61+ let glyph_id = GlyphId :: new ( glyph as u32 ) ;
7562
76- if let Some ( outline_glyph) = outlines. get ( glyph ) {
63+ if let Some ( outline_glyph) = outlines. get ( glyph_id ) {
7764 outline_glyph
7865 . draw (
7966 DrawSettings :: unhinted ( Size :: unscaled ( ) , & self . location ) ,
@@ -84,12 +71,25 @@ pub(crate) mod skrifa {
8471
8572 let path = outline_builder. path ;
8673
74+ let simple_glyph = SimpleGlyph :: from_bezpath ( & path) . ok ( ) ?;
75+ let advance = metrics. advance_width ( glyph_id) ?. round ( ) as u16 ;
76+
77+ // We derive the LSB from the resulting bounding box rather than
78+ // from the font's metrics, because the latter does not always agree
79+ // with the `xMin` of the fresh outline we've generated.
80+ //
81+ // The OpenType spec heavily advises xMin and LSB to match (it
82+ // actually requires it for variable fonts or when `head.flags` bit
83+ // 1 is set).
84+ //
85+ // If `LSB != xMin`, glyphs get repositioned by PDF readers and the
86+ // kerning gets very wonky.
87+ let lsb = simple_glyph. bbox . x_min ;
88+
8789 if path. is_empty ( ) {
88- return Some ( vec ! [ ] ) ;
90+ return Some ( ( advance , lsb , vec ! [ ] ) ) ;
8991 }
9092
91- let simple_glyph = SimpleGlyph :: from_bezpath ( & path) . ok ( ) ?;
92-
9393 maxp_data. max_points = maxp_data
9494 . max_points
9595 . max ( simple_glyph. contours . iter ( ) . map ( |c| c. len ( ) as u16 ) . sum ( ) ) ;
@@ -98,8 +98,9 @@ pub(crate) mod skrifa {
9898
9999 let mut writer = TableWriter :: default ( ) ;
100100 simple_glyph. write_into ( & mut writer) ;
101+ let data = dump_table ( & simple_glyph) . ok ( ) ?;
101102
102- dump_table ( & simple_glyph ) . ok ( )
103+ Some ( ( advance , lsb , data ) )
103104 }
104105 }
105106
0 commit comments