@@ -11,6 +11,7 @@ use crate::fonts::{self, FontLibrary};
1111use crate :: shaper:: { GlyphRun , PartMetrics } ;
1212use crate :: { Align , Range , Vec2 } ;
1313use smallvec:: SmallVec ;
14+ use std:: num:: NonZeroUsize ;
1415use tinyvec:: TinyVec ;
1516use unicode_bidi:: { LTR_LEVEL , Level } ;
1617
@@ -91,13 +92,15 @@ impl TextDisplay {
9192
9293 /// Measure required vertical height, wrapping as configured
9394 ///
95+ /// Stops after `max_lines`, if provided.
96+ ///
9497 /// [Requires status][Self#status-of-preparation]: level runs have been
9598 /// prepared.
96- pub fn measure_height ( & self , wrap_width : f32 ) -> f32 {
99+ pub fn measure_height ( & self , wrap_width : f32 , max_lines : Option < NonZeroUsize > ) -> f32 {
97100 #[ derive( Default ) ]
98101 struct MeasureAdder {
99102 parts : Vec < usize > , // run index for each part
100- has_any_lines : bool ,
103+ lines : usize ,
101104 line_gap : f32 ,
102105 vcaret : f32 ,
103106 }
@@ -107,6 +110,10 @@ impl TextDisplay {
107110 self . parts . len ( )
108111 }
109112
113+ fn num_lines ( & self ) -> usize {
114+ self . lines
115+ }
116+
110117 fn add_part (
111118 & mut self ,
112119 _: & [ GlyphRun ] ,
@@ -152,7 +159,7 @@ impl TextDisplay {
152159 line_gap = line_gap. max ( scale_font. line_gap ( ) ) ;
153160 }
154161
155- if self . has_any_lines {
162+ if self . lines > 0 {
156163 self . vcaret += line_gap. max ( self . line_gap ) ;
157164 }
158165 self . vcaret += ascent - descent;
@@ -161,13 +168,14 @@ impl TextDisplay {
161168 // Vertically align lines to the nearest pixel (improves rendering):
162169 self . vcaret = self . vcaret . round ( ) ;
163170
164- self . has_any_lines = true ;
171+ self . lines += 1 ;
165172 self . parts . clear ( ) ;
166173 }
167174 }
168175
169176 let mut adder = MeasureAdder :: default ( ) ;
170- self . wrap_lines ( & mut adder, wrap_width) ;
177+ let max_lines = max_lines. map ( |n| n. get ( ) ) . unwrap_or ( 0 ) ;
178+ self . wrap_lines ( & mut adder, wrap_width, max_lines) ;
171179 adder. vcaret
172180 }
173181
@@ -206,7 +214,7 @@ impl TextDisplay {
206214 debug_assert ! ( width_bound. is_finite( ) ) ;
207215 let mut adder = LineAdder :: new ( width_bound, h_align) ;
208216
209- self . wrap_lines ( & mut adder, wrap_width) ;
217+ self . wrap_lines ( & mut adder, wrap_width, 0 ) ;
210218
211219 self . wrapped_runs = adder. wrapped_runs ;
212220 self . lines = adder. lines ;
@@ -219,7 +227,12 @@ impl TextDisplay {
219227 adder. vcaret
220228 }
221229
222- fn wrap_lines ( & self , accumulator : & mut impl PartAccumulator , wrap_width : f32 ) {
230+ fn wrap_lines (
231+ & self ,
232+ accumulator : & mut impl PartAccumulator ,
233+ wrap_width : f32 ,
234+ max_lines : usize ,
235+ ) {
223236 let fonts = fonts:: library ( ) ;
224237
225238 // Tuples: (index, part_index, num_parts)
@@ -262,6 +275,10 @@ impl TextDisplay {
262275 // Add up to last valid break point then wrap and reset
263276 accumulator. add_line ( fonts, & self . runs , end. 2 , true ) ;
264277
278+ if accumulator. num_lines ( ) == max_lines {
279+ return ;
280+ }
281+
265282 end. 2 = 0 ;
266283 start = end;
267284 caret = 0.0 ;
@@ -294,6 +311,10 @@ impl TextDisplay {
294311 debug_assert_eq ! ( num_parts, end. 2 ) ;
295312
296313 accumulator. add_line ( fonts, & self . runs , num_parts, false ) ;
314+
315+ if accumulator. num_lines ( ) == max_lines {
316+ return ;
317+ }
297318 }
298319
299320 start = ( run_index, 0 , 0 ) ;
@@ -350,6 +371,7 @@ impl TextDisplay {
350371
351372trait PartAccumulator {
352373 fn num_parts ( & self ) -> usize ;
374+ fn num_lines ( & self ) -> usize ;
353375
354376 fn add_part (
355377 & mut self ,
@@ -404,6 +426,10 @@ impl PartAccumulator for LineAdder {
404426 self . parts . len ( )
405427 }
406428
429+ fn num_lines ( & self ) -> usize {
430+ self . lines . len ( )
431+ }
432+
407433 fn add_part (
408434 & mut self ,
409435 runs : & [ GlyphRun ] ,
0 commit comments