1
1
use crate :: vector:: PointId ;
2
2
use bezier_rs:: { ManipulatorGroup , Subpath } ;
3
3
use core:: cell:: RefCell ;
4
- use glam:: DVec2 ;
4
+ use glam:: { DAffine2 , DVec2 } ;
5
5
use parley:: fontique:: Blob ;
6
6
use parley:: { Alignment , AlignmentOptions , FontContext , GlyphRun , Layout , LayoutContext , LineHeight , PositionedLayoutItem , StyleProperty } ;
7
7
use skrifa:: GlyphId ;
@@ -18,6 +18,7 @@ thread_local! {
18
18
19
19
struct PathBuilder {
20
20
current_subpath : Subpath < PointId > ,
21
+ glyph_subpaths : Vec < Subpath < PointId > > ,
21
22
other_subpaths : Vec < Subpath < PointId > > ,
22
23
origin : DVec2 ,
23
24
scale : f64 ,
@@ -33,21 +34,29 @@ impl PathBuilder {
33
34
self . origin = DVec2 :: new ( x, y) ;
34
35
}
35
36
36
- fn draw_glyph ( & mut self , glyph : & OutlineGlyph < ' _ > , size : f32 , normalized_coords : & [ NormalizedCoord ] ) {
37
+ fn draw_glyph ( & mut self , glyph : & OutlineGlyph < ' _ > , size : f32 , normalized_coords : & [ NormalizedCoord ] , style_skew : Option < DAffine2 > , skew : DAffine2 ) {
37
38
let location_ref = LocationRef :: new ( normalized_coords) ;
38
39
let settings = DrawSettings :: unhinted ( Size :: new ( size) , location_ref) ;
39
40
glyph. draw ( settings, self ) . unwrap ( ) ;
40
41
41
- if !self . current_subpath . is_empty ( ) {
42
- self . other_subpaths . push ( core:: mem:: replace ( & mut self . current_subpath , Subpath :: new ( Vec :: new ( ) , false ) ) ) ;
42
+ for glyph_subpath in & mut self . glyph_subpaths {
43
+ if let Some ( style_skew) = style_skew {
44
+ glyph_subpath. apply_transform ( style_skew) ;
45
+ }
46
+
47
+ glyph_subpath. apply_transform ( skew) ;
48
+ }
49
+
50
+ if !self . glyph_subpaths . is_empty ( ) {
51
+ self . other_subpaths . extend ( core:: mem:: take ( & mut self . glyph_subpaths ) ) ;
43
52
}
44
53
}
45
54
}
46
55
47
56
impl OutlinePen for PathBuilder {
48
57
fn move_to ( & mut self , x : f32 , y : f32 ) {
49
58
if !self . current_subpath . is_empty ( ) {
50
- self . other_subpaths . push ( std:: mem:: replace ( & mut self . current_subpath , Subpath :: new ( Vec :: new ( ) , false ) ) ) ;
59
+ self . glyph_subpaths . push ( std:: mem:: replace ( & mut self . current_subpath , Subpath :: new ( Vec :: new ( ) , false ) ) ) ;
51
60
}
52
61
self . current_subpath . push_manipulator_group ( ManipulatorGroup :: new_anchor_with_id ( self . point ( x, y) , self . id . next_id ( ) ) ) ;
53
62
}
@@ -71,7 +80,7 @@ impl OutlinePen for PathBuilder {
71
80
72
81
fn close ( & mut self ) {
73
82
self . current_subpath . set_closed ( true ) ;
74
- self . other_subpaths . push ( std:: mem:: replace ( & mut self . current_subpath , Subpath :: new ( Vec :: new ( ) , false ) ) ) ;
83
+ self . glyph_subpaths . push ( std:: mem:: replace ( & mut self . current_subpath , Subpath :: new ( Vec :: new ( ) , false ) ) ) ;
75
84
}
76
85
}
77
86
@@ -82,6 +91,7 @@ pub struct TypesettingConfig {
82
91
pub character_spacing : f64 ,
83
92
pub max_width : Option < f64 > ,
84
93
pub max_height : Option < f64 > ,
94
+ pub shear : f64 ,
85
95
}
86
96
87
97
impl Default for TypesettingConfig {
@@ -92,16 +102,28 @@ impl Default for TypesettingConfig {
92
102
character_spacing : 0. ,
93
103
max_width : None ,
94
104
max_height : None ,
105
+ shear : 0. ,
95
106
}
96
107
}
97
108
}
98
109
99
- fn render_glyph_run ( glyph_run : & GlyphRun < ' _ , ( ) > , path_builder : & mut PathBuilder ) {
110
+ fn render_glyph_run ( glyph_run : & GlyphRun < ' _ , ( ) > , path_builder : & mut PathBuilder , shear : f64 ) {
100
111
let mut run_x = glyph_run. offset ( ) ;
101
112
let run_y = glyph_run. baseline ( ) ;
102
113
103
114
let run = glyph_run. run ( ) ;
104
115
116
+ let skew = DAffine2 :: from_translation ( DVec2 :: new ( 0.0 , run_y as f64 ) )
117
+ * DAffine2 :: from_cols_array ( & [ 1.0 , 0.0 , -shear. to_radians ( ) . tan ( ) as f64 , 1.0 , 0.0 , 0.0 ] )
118
+ * DAffine2 :: from_translation ( DVec2 :: new ( 0.0 , -run_y as f64 ) ) ;
119
+
120
+ let synthesis = run. synthesis ( ) ;
121
+ let style_skew = synthesis. skew ( ) . map ( |angle| {
122
+ DAffine2 :: from_translation ( DVec2 :: new ( 0.0 , run_y as f64 ) )
123
+ * DAffine2 :: from_cols_array ( & [ 1.0 , 0.0 , -angle. to_radians ( ) . tan ( ) as f64 , 1.0 , 0.0 , 0.0 ] )
124
+ * DAffine2 :: from_translation ( DVec2 :: new ( 0.0 , -run_y as f64 ) )
125
+ } ) ;
126
+
105
127
let font = run. font ( ) ;
106
128
let font_size = run. font_size ( ) ;
107
129
@@ -120,7 +142,7 @@ fn render_glyph_run(glyph_run: &GlyphRun<'_, ()>, path_builder: &mut PathBuilder
120
142
let glyph_id = GlyphId :: from ( glyph. id ) ;
121
143
if let Some ( glyph_outline) = outlines. get ( glyph_id) {
122
144
path_builder. set_origin ( glyph_x as f64 , glyph_y as f64 ) ;
123
- path_builder. draw_glyph ( & glyph_outline, font_size, & normalized_coords) ;
145
+ path_builder. draw_glyph ( & glyph_outline, font_size, & normalized_coords, style_skew , skew ) ;
124
146
}
125
147
}
126
148
}
@@ -160,6 +182,7 @@ pub fn to_path(str: &str, font_data: Option<Blob<u8>>, typesetting: TypesettingC
160
182
161
183
let mut path_builder = PathBuilder {
162
184
current_subpath : Subpath :: new ( Vec :: new ( ) , false ) ,
185
+ glyph_subpaths : Vec :: new ( ) ,
163
186
other_subpaths : Vec :: new ( ) ,
164
187
origin : DVec2 :: ZERO ,
165
188
scale : layout. scale ( ) as f64 ,
@@ -170,7 +193,7 @@ pub fn to_path(str: &str, font_data: Option<Blob<u8>>, typesetting: TypesettingC
170
193
for item in line. items ( ) {
171
194
match item {
172
195
PositionedLayoutItem :: GlyphRun ( glyph_run) => {
173
- render_glyph_run ( & glyph_run, & mut path_builder) ;
196
+ render_glyph_run ( & glyph_run, & mut path_builder, typesetting . shear ) ;
174
197
}
175
198
PositionedLayoutItem :: InlineBox ( _inline_box) => {
176
199
// Render the inline box
0 commit comments