1
- use ab_glyph:: { PxScale , ScaleFont } ;
1
+ use ab_glyph:: { Font as AbFont , PxScale , ScaleFont } ;
2
2
use bevy_asset:: { Assets , Handle , HandleId } ;
3
3
use bevy_ecs:: component:: Component ;
4
4
use bevy_ecs:: system:: Resource ;
@@ -7,11 +7,12 @@ use bevy_render::texture::Image;
7
7
use bevy_sprite:: TextureAtlas ;
8
8
use bevy_utils:: HashMap ;
9
9
10
- use glyph_brush_layout:: { FontId , GlyphPositioner , SectionGeometry , SectionText } ;
10
+ use glyph_brush_layout:: { FontId , GlyphPositioner , SectionGeometry , SectionText , ToSectionText } ;
11
11
12
12
use crate :: {
13
13
error:: TextError , glyph_brush:: GlyphBrush , scale_value, BreakLineOn , Font , FontAtlasSet ,
14
- FontAtlasWarning , PositionedGlyph , TextAlignment , TextSection , TextSettings , YAxisOrientation ,
14
+ FontAtlasWarning , PositionedGlyph , Text , TextAlignment , TextSection , TextSettings ,
15
+ YAxisOrientation ,
15
16
} ;
16
17
17
18
#[ derive( Default , Resource ) ]
@@ -117,116 +118,93 @@ impl TextPipeline {
117
118
118
119
Ok ( TextLayoutInfo { glyphs, size } )
119
120
}
121
+ }
120
122
121
- pub fn create_text_measure (
122
- & mut self ,
123
+ #[ derive( Debug , Clone ) ]
124
+ pub struct TextMeasureSection {
125
+ pub text : Box < str > ,
126
+ pub scale : f32 ,
127
+ pub font_id : FontId ,
128
+ }
129
+
130
+ #[ derive( Debug , Clone , Default ) ]
131
+ pub struct TextMeasureInfo {
132
+ pub fonts : Box < [ ab_glyph:: FontArc ] > ,
133
+ pub sections : Box < [ TextMeasureSection ] > ,
134
+ pub text_alignment : TextAlignment ,
135
+ pub linebreak_behavior : glyph_brush_layout:: BuiltInLineBreaker ,
136
+ pub min : Vec2 ,
137
+ pub max : Vec2 ,
138
+ }
139
+
140
+ impl TextMeasureInfo {
141
+ pub fn from_text (
142
+ text : & Text ,
123
143
fonts : & Assets < Font > ,
124
- sections : & [ TextSection ] ,
125
144
scale_factor : f64 ,
126
- text_alignment : TextAlignment ,
127
- linebreak_behaviour : BreakLineOn ,
128
145
) -> Result < TextMeasureInfo , TextError > {
129
- let mut auto_fonts = Vec :: with_capacity ( sections. len ( ) ) ;
130
- let mut scaled_fonts = Vec :: with_capacity ( sections. len ( ) ) ;
131
- let sections = sections
146
+ let sections = & text. sections ;
147
+ for section in sections {
148
+ if !fonts. contains ( & section. style . font ) {
149
+ return Err ( TextError :: NoSuchFont ) ;
150
+ }
151
+ }
152
+ let ( auto_fonts, sections) = sections
132
153
. iter ( )
133
154
. enumerate ( )
134
155
. map ( |( i, section) | {
135
- let font = fonts
136
- . get ( & section. style . font )
137
- . ok_or ( TextError :: NoSuchFont ) ?;
138
- let font_size = scale_value ( section. style . font_size , scale_factor) ;
139
- auto_fonts. push ( font. font . clone ( ) ) ;
140
- let px_scale_font = ab_glyph:: Font :: into_scaled ( font. font . clone ( ) , font_size) ;
141
- scaled_fonts. push ( px_scale_font) ;
142
-
143
- let section = TextMeasureSection {
144
- font_id : FontId ( i) ,
145
- scale : PxScale :: from ( font_size) ,
146
- text : section. value . clone ( ) ,
147
- } ;
148
-
149
- Ok ( section)
156
+ // SAFETY: we exited early earlier in this function if
157
+ // one of the fonts was missing.
158
+ let font = unsafe { fonts. get ( & section. style . font ) . unwrap_unchecked ( ) } ;
159
+ (
160
+ font. font . clone ( ) ,
161
+ TextMeasureSection {
162
+ font_id : FontId ( i) ,
163
+ scale : scale_value ( section. style . font_size , scale_factor) ,
164
+ text : section. value . clone ( ) . into_boxed_str ( ) ,
165
+ } ,
166
+ )
150
167
} )
151
- . collect :: < Result < Vec < _ > , _ > > ( ) ? ;
168
+ . unzip ( ) ;
152
169
153
- Ok ( TextMeasureInfo :: new (
170
+ Ok ( Self :: new (
154
171
auto_fonts,
155
- scaled_fonts,
156
172
sections,
157
- text_alignment ,
158
- linebreak_behaviour . into ( ) ,
173
+ text . alignment ,
174
+ text . linebreak_behavior . into ( ) ,
159
175
) )
160
176
}
161
- }
162
-
163
- #[ derive( Debug , Clone ) ]
164
- pub struct TextMeasureSection {
165
- pub text : String ,
166
- pub scale : PxScale ,
167
- pub font_id : FontId ,
168
- }
169
-
170
- #[ derive( Debug , Clone ) ]
171
- pub struct TextMeasureInfo {
172
- pub fonts : Vec < ab_glyph:: FontArc > ,
173
- pub scaled_fonts : Vec < ab_glyph:: PxScaleFont < ab_glyph:: FontArc > > ,
174
- pub sections : Vec < TextMeasureSection > ,
175
- pub text_alignment : TextAlignment ,
176
- pub linebreak_behaviour : glyph_brush_layout:: BuiltInLineBreaker ,
177
- pub min_width_content_size : Vec2 ,
178
- pub max_width_content_size : Vec2 ,
179
- }
180
-
181
- impl TextMeasureInfo {
182
177
fn new (
183
178
fonts : Vec < ab_glyph:: FontArc > ,
184
- scaled_fonts : Vec < ab_glyph:: PxScaleFont < ab_glyph:: FontArc > > ,
185
179
sections : Vec < TextMeasureSection > ,
186
180
text_alignment : TextAlignment ,
187
- linebreak_behaviour : glyph_brush_layout:: BuiltInLineBreaker ,
181
+ linebreak_behavior : glyph_brush_layout:: BuiltInLineBreaker ,
188
182
) -> Self {
189
183
let mut info = Self {
190
- fonts,
191
- scaled_fonts,
192
- sections,
184
+ fonts : fonts. into_boxed_slice ( ) ,
185
+ sections : sections. into_boxed_slice ( ) ,
193
186
text_alignment,
194
- linebreak_behaviour ,
195
- min_width_content_size : Vec2 :: ZERO ,
196
- max_width_content_size : Vec2 :: ZERO ,
187
+ linebreak_behavior ,
188
+ min : Vec2 :: ZERO ,
189
+ max : Vec2 :: ZERO ,
197
190
} ;
198
191
199
- let section_texts = info. prepare_section_texts ( ) ;
200
- let min =
201
- info. compute_size_from_section_texts ( & section_texts, Vec2 :: new ( 0.0 , f32:: INFINITY ) ) ;
202
- let max = info. compute_size_from_section_texts (
203
- & section_texts,
204
- Vec2 :: new ( f32:: INFINITY , f32:: INFINITY ) ,
205
- ) ;
206
- info. min_width_content_size = min;
207
- info. max_width_content_size = max;
192
+ let min = info. compute_size ( Vec2 :: new ( 0.0 , f32:: INFINITY ) ) ;
193
+ let max = info. compute_size ( Vec2 :: INFINITY ) ;
194
+ info. min = min;
195
+ info. max = max;
208
196
info
209
197
}
210
198
211
- fn prepare_section_texts ( & self ) -> Vec < SectionText > {
212
- self . sections
213
- . iter ( )
214
- . map ( |section| SectionText {
215
- font_id : section. font_id ,
216
- scale : section. scale ,
217
- text : & section. text ,
218
- } )
219
- . collect :: < Vec < _ > > ( )
220
- }
221
-
222
- fn compute_size_from_section_texts ( & self , sections : & [ SectionText ] , bounds : Vec2 ) -> Vec2 {
199
+ pub fn compute_size ( & self , bounds : Vec2 ) -> Vec2 {
200
+ let sections = & self . sections ;
223
201
let geom = SectionGeometry {
224
202
bounds : ( bounds. x , bounds. y ) ,
225
203
..Default :: default ( )
226
204
} ;
227
205
let section_glyphs = glyph_brush_layout:: Layout :: default ( )
228
206
. h_align ( self . text_alignment . into ( ) )
229
- . line_breaker ( self . linebreak_behaviour )
207
+ . line_breaker ( self . linebreak_behavior )
230
208
. calculate_glyphs ( & self . fonts , & geom, sections) ;
231
209
232
210
let mut min_x: f32 = std:: f32:: MAX ;
@@ -235,7 +213,10 @@ impl TextMeasureInfo {
235
213
let mut max_y: f32 = std:: f32:: MIN ;
236
214
237
215
for sg in section_glyphs {
238
- let scaled_font = & self . scaled_fonts [ sg. section_index ] ;
216
+ let font = & self . fonts [ sg. section_index ] ;
217
+ let font_size = self . sections [ sg. section_index ] . scale ;
218
+ let scaled_font = font. into_scaled ( font_size) ;
219
+
239
220
let glyph = & sg. glyph ;
240
221
// The fonts use a coordinate system increasing upwards so ascent is a positive value
241
222
// and descent is negative, but Bevy UI uses a downwards increasing coordinate system,
@@ -248,9 +229,14 @@ impl TextMeasureInfo {
248
229
249
230
Vec2 :: new ( max_x - min_x, max_y - min_y)
250
231
}
251
-
252
- pub fn compute_size ( & self , bounds : Vec2 ) -> Vec2 {
253
- let sections = self . prepare_section_texts ( ) ;
254
- self . compute_size_from_section_texts ( & sections, bounds)
232
+ }
233
+ impl ToSectionText for TextMeasureSection {
234
+ #[ inline( always) ]
235
+ fn to_section_text ( & self ) -> SectionText < ' _ > {
236
+ SectionText {
237
+ text : & self . text ,
238
+ scale : PxScale :: from ( self . scale ) ,
239
+ font_id : self . font_id ,
240
+ }
255
241
}
256
242
}
0 commit comments