Skip to content

Commit 76ab37d

Browse files
authored
On overflow, right-align RTL-text (#268)
As text should be start-aligned on overflow when `overflow_alignment` is `false`, RTL-text must be right-aligned in this case.
1 parent ab01c9d commit 76ab37d

File tree

7 files changed

+56
-3
lines changed

7 files changed

+56
-3
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ This release has an [MSRV] of 1.82.
4343

4444
#### Parley
4545

46-
- Fix alignment of right-to-left text. ([#250][] by [@tomcur][])
46+
- Fix alignment of right-to-left text. ([#250][], [#268][] by [@tomcur][])
4747

4848
## [0.2.0] - 2024-10-10
4949

@@ -124,6 +124,7 @@ This release has an [MSRV] of 1.70.
124124
[#223]: https://github.com/linebender/parley/pull/223
125125
[#224]: https://github.com/linebender/parley/pull/224
126126
[#250]: https://github.com/linebender/parley/pull/250
127+
[#268]: https://github.com/linebender/parley/pull/268
127128

128129
[Unreleased]: https://github.com/linebender/parley/compare/v0.2.0...HEAD
129130
[0.2.0]: https://github.com/linebender/parley/releases/tag/v0.2.0

parley/src/layout/alignment.rs

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ pub(crate) fn align<B: Brush>(
3434
let free_space = alignment_width - line.metrics.advance + line.metrics.trailing_whitespace;
3535

3636
if !align_when_overflowing && free_space <= 0.0 {
37+
if is_rtl {
38+
// In RTL text, right-align on overflow.
39+
line.metrics.offset = free_space;
40+
}
3741
continue;
3842
}
3943

parley/src/tests/test_basic.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2024 the Parley Authors
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

4+
use peniko::kurbo::Size;
5+
46
use crate::{testenv, Alignment, InlineBox, WhiteSpaceCollapse};
57

68
#[test]
@@ -197,3 +199,22 @@ fn base_level_alignment_rtl() {
197199
env.with_name(test_case_name).check_layout_snapshot(&layout);
198200
}
199201
}
202+
203+
#[test]
204+
/// On overflow without alignment-on-overflow, RTL-text should be start-aligned (i.e., aligned to
205+
/// the right edge, overflowing on the left).
206+
fn overflow_alignment_rtl() {
207+
let mut env = testenv!();
208+
209+
let text = "عند برمجة أجهزة الكمبيوتر، قد تجد نفسك فجأة في مواقف غريبة، مثل الكتابة بلغة لا تتحدثها فعليًا.";
210+
let mut builder = env.ranged_builder(text);
211+
let mut layout = builder.build(text);
212+
layout.break_all_lines(Some(1000.0));
213+
layout.align(
214+
Some(10.),
215+
Alignment::Middle,
216+
false, /* align_when_overflowing */
217+
);
218+
env.rendering_config().size = Some(Size::new(10., layout.height().into()));
219+
env.check_layout_snapshot(&layout);
220+
}

parley/src/tests/utils/cursor_test.rs

+3
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,14 @@ impl CursorTest {
195195
inline_box_color: bg_color_expected,
196196
cursor_color: cursor_color_expected,
197197
selection_color: selection_color_expected,
198+
size: None,
198199
};
199200
let rendering_config_actual = RenderingConfig {
200201
background_color: bg_color_actual,
201202
inline_box_color: bg_color_actual,
202203
cursor_color: cursor_color_actual,
203204
selection_color: selection_color_actual,
205+
size: None,
204206
};
205207

206208
let rect_expected = expected.geometry(&self.layout, CURSOR_WIDTH);
@@ -357,6 +359,7 @@ impl CursorTest {
357359
inline_box_color: bg_color_cursor,
358360
cursor_color: cursor_color_cursor,
359361
selection_color: selection_color_cursor,
362+
size: None,
360363
};
361364

362365
let rect_cursor = cursor.geometry(&self.layout, CURSOR_WIDTH);

parley/src/tests/utils/env.rs

+5
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,18 @@ impl TestEnv {
151151
cursor_color: Color::from_rgba8(255, 0, 0, 255),
152152
selection_color: Color::from_rgba8(196, 196, 0, 255),
153153
inline_box_color: Color::BLACK,
154+
size: None,
154155
},
155156
cursor_size: 2.0,
156157
errors: Vec::new(),
157158
next_test_case_name: String::new(),
158159
}
159160
}
160161

162+
pub(crate) fn rendering_config(&mut self) -> &mut RenderingConfig {
163+
&mut self.rendering_config
164+
}
165+
161166
fn default_style(&self) -> [StyleProperty<'static, ColorBrush>; 2] {
162167
[
163168
StyleProperty::Brush(ColorBrush {

parley/src/tests/utils/renderer.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! if you need emoji rendering.
99
1010
use crate::{GlyphRun, Layout, PositionedLayoutItem};
11+
use peniko::kurbo;
1112
use skrifa::{
1213
instance::{LocationRef, NormalizedCoord, Size},
1314
outline::{DrawSettings, OutlinePen},
@@ -34,6 +35,9 @@ pub(crate) struct RenderingConfig {
3435
pub inline_box_color: Color,
3536
pub cursor_color: Color,
3637
pub selection_color: Color,
38+
39+
/// The width of the pixmap in pixels, excluding padding.
40+
pub size: Option<kurbo::Size>,
3741
}
3842

3943
fn draw_rect(pen: &mut TinySkiaPen<'_>, x: f32, y: f32, width: f32, height: f32, color: Color) {
@@ -42,15 +46,27 @@ fn draw_rect(pen: &mut TinySkiaPen<'_>, x: f32, y: f32, width: f32, height: f32,
4246
pen.fill_rect(width, height);
4347
}
4448

49+
/// Render the layout to a [`Pixmap`].
50+
///
51+
/// If given [`RenderingConfig::size`] is not specified, [`Layout::width`] and [`Layout::height`]
52+
/// are used.
4553
pub(crate) fn render_layout(
4654
config: &RenderingConfig,
4755
layout: &Layout<ColorBrush>,
4856
cursor_rect: Option<crate::Rect>,
4957
selection_rects: &[crate::Rect],
5058
) -> Pixmap {
5159
let padding = 20;
52-
let width = layout.width().ceil() as u32;
53-
let height = layout.height().ceil() as u32;
60+
let width = config
61+
.size
62+
.map(|size| size.width as f32)
63+
.unwrap_or(layout.width())
64+
.ceil() as u32;
65+
let height = config
66+
.size
67+
.map(|size| size.height as f32)
68+
.unwrap_or(layout.height())
69+
.ceil() as u32;
5470
let padded_width = width + padding * 2;
5571
let padded_height = height + padding * 2;
5672
let fpadding = padding as f32;
Loading

0 commit comments

Comments
 (0)