Skip to content

Commit 898e1f7

Browse files
committed
Implement LayoutJob::round_output_to_gui
1 parent 6ef0c74 commit 898e1f7

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

crates/epaint/src/text/parley_layout.rs

+37-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::sync::Arc;
22

33
use ecolor::Color32;
4-
use emath::{pos2, vec2, Pos2, Rect, Vec2};
4+
use emath::{pos2, vec2, GuiRounding, NumExt, Pos2, Rect, Vec2};
55
use log::debug;
66
use parley::{AlignmentOptions, BreakReason, GlyphRun, InlineBox, PositionedLayoutItem};
77

@@ -95,12 +95,15 @@ pub(super) fn layout(fonts: &mut FontsLayoutView<'_>, job: LayoutJob) -> Galley
9595

9696
let mut overflow_char_layout = None;
9797

98-
let max_width = job.wrap.max_width.is_finite().then_some(job.wrap.max_width);
9998
let mut break_lines = layout.break_lines();
10099
for i in 0..job.wrap.max_rows {
101-
let width = max_width.unwrap_or(f32::MAX);
102-
103-
let line = break_lines.break_next(width);
100+
let wrap_width = job.effective_wrap_width();
101+
let wrap_width = if wrap_width.is_finite() {
102+
wrap_width
103+
} else {
104+
f32::MAX
105+
};
106+
let line = break_lines.break_next(wrap_width);
104107

105108
// We're truncating the text with an overflow character.
106109
if let (Some(overflow_character), true, true) = (
@@ -118,7 +121,7 @@ pub(super) fn layout(fonts: &mut FontsLayoutView<'_>, job: LayoutJob) -> Galley
118121
layout.break_all_lines(None);
119122

120123
break_lines.revert();
121-
break_lines.break_next(width - layout.full_width());
124+
break_lines.break_next(wrap_width - layout.full_width());
122125
overflow_char_layout = Some((layout, Vec2::ZERO));
123126
}
124127

@@ -133,7 +136,14 @@ pub(super) fn layout(fonts: &mut FontsLayoutView<'_>, job: LayoutJob) -> Galley
133136
// case, that could occur due to floating-point error if we use
134137
// `layout.width()` as the alignment width, but it's okay as left-alignment
135138
// will look the same as the "correct" alignment.
136-
let alignment_width = max_width.unwrap_or_else(|| layout.width());
139+
//
140+
// Note that we only use the "effective wrap width" for determining line
141+
// breaks. Everywhere else, we want to use the actual specified width.
142+
let alignment_width = if job.wrap.max_width.is_finite() {
143+
job.wrap.max_width
144+
} else {
145+
layout.width()
146+
};
137147
let horiz_offset = match (justify, job.halign) {
138148
(false, emath::Align::Center) => -alignment_width * 0.5,
139149
(false, emath::Align::RIGHT) => -alignment_width,
@@ -395,6 +405,22 @@ pub(super) fn layout(fonts: &mut FontsLayoutView<'_>, job: LayoutJob) -> Galley
395405
pos2(line_start, line_metrics.min_coord + vertical_offset),
396406
pos2(line_end, line_metrics.max_coord + vertical_offset),
397407
));
408+
409+
if job.round_output_to_gui {
410+
let did_exceed_wrap_width_by_a_lot =
411+
row_logical_bounds.max.x > job.wrap.max_width + 1.0;
412+
413+
row_logical_bounds = row_logical_bounds.round_ui();
414+
415+
if did_exceed_wrap_width_by_a_lot {
416+
// If the user picked a too aggressive wrap width (e.g. more narrow than any individual glyph),
417+
// we should let the user know by reporting that our width is wider than the wrap width.
418+
} else {
419+
// Make sure we don't report being wider than the wrap width the user picked:
420+
row_logical_bounds.max.x = row_logical_bounds.max.x.at_most(job.wrap.max_width);
421+
}
422+
}
423+
398424
acc_logical_bounds = acc_logical_bounds.union(row_logical_bounds);
399425

400426
if acc_logical_bounds.width() > job.wrap.max_width {
@@ -461,6 +487,10 @@ pub(super) fn layout(fonts: &mut FontsLayoutView<'_>, job: LayoutJob) -> Galley
461487
);
462488
}
463489

490+
if job.round_output_to_gui {
491+
acc_logical_bounds = acc_logical_bounds.round_ui();
492+
}
493+
464494
Galley {
465495
job: Arc::new(job),
466496
rows,

crates/epaint/src/text/text_layout_types.rs

-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ pub struct LayoutJob {
8080
pub justify: bool,
8181

8282
/// Round output sizes using [`emath::GuiRounding`], to avoid rounding errors in layout code.
83-
/// TODO(valadaptive): implement this
8483
pub round_output_to_gui: bool,
8584
}
8685

parley-todo.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
- ~~Could it be trailing whitespace?~~
2222
- [ ] In the EasyMark example, with the text "There is no alternative way to specify the strong style", at certain wrap widths, the text from "strong" onwards will be shifted down 1px
2323
- [ ] With the fancy variable autohinted Ubuntu font, *sometimes* the "Interactive Container" label on the right demos bar appears improperly wrapped?
24-
- [ ] With "Text Wrap Mode" set to "Some(Wrap)" or "Some(Truncate)" in the Settings window, labels are not as wide as they should be compared to master branch (see Text Layout window)
25-
- [ ] Text wrapping
24+
- [x] With "Text Wrap Mode" set to "Some(Wrap)" or "Some(Truncate)" in the Settings window, labels are not as wide as they should be compared to master branch (see Text Layout window)
25+
- [x] Text wrapping
2626
- [x] max_rows
2727
- [x] break_anywhere
2828
- [x] overflow_character
29-
- [ ] `LayoutJob::round_output_to_gui`
29+
- [x] `LayoutJob::round_output_to_gui`
3030
- [ ] `LayoutJob::break_on_newline`
3131
- [ ] RTL considerations
3232
- [ ] Label wrapping only occurs in LTR layouts, but make sure it doesn't do anything weird with RTL labels

0 commit comments

Comments
 (0)