Skip to content

Commit 9056db3

Browse files
committed
Add max_lines limit to fn measure_height
1 parent 0a64090 commit 9056db3

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/display/wrap_lines.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::fonts::{self, FontLibrary};
1111
use crate::shaper::{GlyphRun, PartMetrics};
1212
use crate::{Align, Range, Vec2};
1313
use smallvec::SmallVec;
14+
use std::num::NonZeroUsize;
1415
use tinyvec::TinyVec;
1516
use 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

351372
trait 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],

src/text.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::display::{Effect, MarkerPosIter, NotReady, TextDisplay};
99
use crate::fonts::{FontSelector, NoFontMatch};
1010
use crate::format::FormattableText;
1111
use crate::{Align, Direction, GlyphRun, Line, Status, Vec2};
12+
use std::num::NonZeroUsize;
1213

1314
/// Text type-setting object (high-level API)
1415
///
@@ -420,14 +421,16 @@ impl<T: FormattableText + ?Sized> Text<T> {
420421
}
421422

422423
/// Measure required vertical height, wrapping as configured
423-
pub fn measure_height(&mut self) -> Result<f32, NoFontMatch> {
424+
///
425+
/// Stops after `max_lines`, if provided.
426+
pub fn measure_height(&mut self, max_lines: Option<NonZeroUsize>) -> Result<f32, NoFontMatch> {
424427
if self.status >= Status::Wrapped {
425428
let (tl, br) = self.display.bounding_box();
426429
return Ok(br.1 - tl.1);
427430
}
428431

429432
self.prepare_runs()?;
430-
Ok(self.display.measure_height(self.wrap_width))
433+
Ok(self.display.measure_height(self.wrap_width, max_lines))
431434
}
432435

433436
/// Prepare text for display, as necessary

0 commit comments

Comments
 (0)