Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This release has an [MSRV] of 1.88.

#### Parley

- `complex-scripts` Cargo feature to enable dictionary-based line and word breaking for complex scripts (CJK, Thai, Khmer, Lao, Myanmar). When disabled, the lightweight segmenter is used (no change in default behavior).
- `PlainEditor`, `Layout`, `LayoutAccessibility`, and `Generation` now implement `Debug`. ([#615][] by [@NandishwarSingh][])
Note: The `Layout` implementation provides a compact summary by default; the alternate form (`{:#?}`) formats the full underlying data.

Expand Down
3 changes: 3 additions & 0 deletions parley/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ libm = ["fontique/libm", "peniko/libm", "skrifa/libm", "dep:core_maths"]
# Enables support for system font backends
system = ["std", "fontique/system"]
accesskit = ["dep:accesskit"]
# Enables dictionary-based line and word breaking for complex scripts (CJK, Thai, Khmer, Lao, Myanmar).
# When disabled, a lightweight segmenter is used that falls back to character-level breaks for those scripts.
complex-scripts = []

[dependencies]
skrifa = { workspace = true }
Expand Down
45 changes: 29 additions & 16 deletions parley/src/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,33 @@ impl AnalysisDataSources {

#[inline(always)]
fn word_segmenter(&self) -> WordSegmenterBorrowed<'static> {
const { WordSegmenter::new_for_non_complex_scripts(WordBreakInvariantOptions::default()) }
#[cfg(feature = "complex-scripts")]
{
WordSegmenter::new_dictionary(WordBreakInvariantOptions::default())
}
#[cfg(not(feature = "complex-scripts"))]
{
const { WordSegmenter::new_for_non_complex_scripts(WordBreakInvariantOptions::default()) }
}
}

#[inline(always)]
fn line_segmenter(&self, word_break_strength: WordBreak) -> LineSegmenterBorrowed<'static> {
match word_break_strength {
WordBreak::Normal => {
const {
let mut opt = LineBreakOptions::default();
opt.word_option = Some(LineBreakWordOption::Normal);
LineSegmenter::new_for_non_complex_scripts(opt)
}
let mut opt = LineBreakOptions::default();
opt.word_option = Some(LineBreakWordOption::Normal);
line_segmenter_impl(opt)
}
WordBreak::BreakAll => {
const {
let mut opt = LineBreakOptions::default();
opt.word_option = Some(LineBreakWordOption::BreakAll);
LineSegmenter::new_for_non_complex_scripts(opt)
}
let mut opt = LineBreakOptions::default();
opt.word_option = Some(LineBreakWordOption::BreakAll);
line_segmenter_impl(opt)
}
WordBreak::KeepAll => {
const {
let mut opt = LineBreakOptions::default();
opt.word_option = Some(LineBreakWordOption::KeepAll);
LineSegmenter::new_for_non_complex_scripts(opt)
}
let mut opt = LineBreakOptions::default();
opt.word_option = Some(LineBreakWordOption::KeepAll);
line_segmenter_impl(opt)
}
}
Comment on lines 58 to 74

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could probably be simpliflied to:

#[inline(always)]
fn line_segmenter(&self, word_break_strength: WordBreak) -> LineSegmenterBorrowed<'static> {
    let mut opt = LineBreakOptions::default();
    opt.word_option = Some(match word_break_strength {
        WordBreak::Normal => LineBreakWordOption::Normal,
        WordBreak::BreakAll => LineBreakWordOption::BreakAll,
        WordBreak::KeepAll => LineBreakWordOption::KeepAll,
    });
    line_segmenter_impl(opt)
}

But I'm not going to require it as part of this PR seeing it was a pre-existing issue.

}
Expand All @@ -94,6 +95,18 @@ impl AnalysisDataSources {
}
}

#[cfg(feature = "complex-scripts")]
#[inline(always)]
fn line_segmenter_impl(opt: LineBreakOptions<'_>) -> LineSegmenterBorrowed<'static> {
LineSegmenter::new_dictionary(opt)
}

#[cfg(not(feature = "complex-scripts"))]
#[inline(always)]
fn line_segmenter_impl(opt: LineBreakOptions<'_>) -> LineSegmenterBorrowed<'static> {
LineSegmenter::new_for_non_complex_scripts(opt)
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) struct CharInfo {
/// The line/word breaking boundary classification of this character.
Expand Down
Loading