Skip to content

Commit

Permalink
Round text gallye sizes to nearest ui point size
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed May 29, 2024
1 parent 66f40de commit 5098e1d
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
27 changes: 25 additions & 2 deletions crates/epaint/src/text/text_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ fn rows_from_paragraphs(
}

fn line_break(paragraph: &Paragraph, job: &LayoutJob, out_rows: &mut Vec<Row>, elided: &mut bool) {
let wrap_width_margin = if job.round_output_size_to_nearest_ui_point {
0.5
} else {
0.0
};

// Keeps track of good places to insert row break if we exceed `wrap_width`.
let mut row_break_candidates = RowBreakCandidates::default();

Expand All @@ -253,7 +259,7 @@ fn line_break(paragraph: &Paragraph, job: &LayoutJob, out_rows: &mut Vec<Row>, e

let potential_row_width = paragraph.glyphs[i].max_x() - row_start_x;

if job.wrap.max_width < potential_row_width {
if job.wrap.max_width + wrap_width_margin < potential_row_width {
// Row break:

if first_row_indentation > 0.0
Expand Down Expand Up @@ -630,7 +636,24 @@ fn galley_from_rows(
num_indices += row.visuals.mesh.indices.len();
}

let rect = Rect::from_min_max(pos2(min_x, 0.0), pos2(max_x, cursor_y));
let mut rect = Rect::from_min_max(pos2(min_x, 0.0), pos2(max_x, cursor_y));

if job.round_output_size_to_nearest_ui_point {
let did_exceed_wrap_width_by_a_lot = rect.width() > job.wrap.max_width + 1.0;

// We round the size to whole ui points here (not pixels!) so that the egui layout code
// can have the advantage of working in integer units, avoiding rounding errors.
rect.min = rect.min.round();
rect.max = rect.max.round();

if did_exceed_wrap_width_by_a_lot {
// If the user picked a too aggressive wrap width (e.g. more narrow than any individual glyph),
// we should let the user know.
} else {
// Make sure we don't over the max wrap width the user picked:
rect.max.x = rect.max.x.at_most(rect.min.x + job.wrap.max_width);
}
}

Galley {
job,
Expand Down
7 changes: 7 additions & 0 deletions crates/epaint/src/text/text_layout_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ pub struct LayoutJob {

/// Justify text so that word-wrapped rows fill the whole [`TextWrapping::max_width`].
pub justify: bool,

/// Rounding to the closest ui point (not pixel!) allows the rest of the
/// layout code to run on perfect integers, avoiding rounding errors.
pub round_output_size_to_nearest_ui_point: bool,
}

impl Default for LayoutJob {
Expand All @@ -87,6 +91,7 @@ impl Default for LayoutJob {
break_on_newline: true,
halign: Align::LEFT,
justify: false,
round_output_size_to_nearest_ui_point: true,
}
}
}
Expand Down Expand Up @@ -180,6 +185,7 @@ impl std::hash::Hash for LayoutJob {
break_on_newline,
halign,
justify,
round_output_size_to_nearest_ui_point,
} = self;

text.hash(state);
Expand All @@ -189,6 +195,7 @@ impl std::hash::Hash for LayoutJob {
break_on_newline.hash(state);
halign.hash(state);
justify.hash(state);
round_output_size_to_nearest_ui_point.hash(state);
}
}

Expand Down

0 comments on commit 5098e1d

Please sign in to comment.