Skip to content

Commit bf3debd

Browse files
authored
Move bidi algorithm into parley_core (linebender#647)
Kicking off the sequence to end up at (roughly) the shape of linebender#634. Instead of starting with `parley_data`, I figured to first move the bidi algorithm as it wires up the `parley` and `parley_core` crates plus handles some lints that `parley` suppressed and `parley_core` doesn't. Two more PRs are ready: first, simply moving the line break opportunity overrides introduced in linebender#640 (similarly moving files and handling lints), second and more interestingly, migrating `parley`'s analysis without any real changes into `parley_core` and introducing `parley_core::{Analysis, Analyzer}`.
1 parent 033e0b0 commit bf3debd

9 files changed

Lines changed: 46 additions & 25 deletions

File tree

Cargo.lock

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ repository = "https://github.com/linebender/parley"
3737
parlance = { version = "0.1.0", default-features = false, path = "parlance" }
3838
fontique = { version = "0.11.0", default-features = false, path = "fontique" }
3939
parley = { version = "0.11.0", default-features = false, path = "parley" }
40+
parley_core = { version = "0.11.0", default-features = false, path = "parley_core" }
4041
parley_data = { version = "0.11.0", path = "parley_data", default-features = false }
4142
parley_data_gen = { path = "parley_data_gen" }
4243
parley_dev = { default-features = false, path = "parley_dev" }

parley/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ skrifa = { workspace = true }
3232
linebender_resource_handle = { workspace = true }
3333
fontique = { workspace = true }
3434
parlance = { workspace = true }
35+
parley_core = { workspace = true }
3536
core_maths = { version = "0.1.1", optional = true }
3637
parley_data = { workspace = true, features = ["baked"] }
3738
accesskit = { workspace = true, optional = true }

parley/src/analysis/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use icu_segmenter::{
2525
};
2626
use parley_data::Properties;
2727

28+
use parley_core::bidi;
29+
2830
pub(crate) struct AnalysisDataSources;
2931

3032
impl AnalysisDataSources {
@@ -511,7 +513,7 @@ pub(crate) fn analyze_text<B: Brush>(
511513
}
512514
};
513515

514-
needs_bidi_resolution |= crate::bidi::needs_bidi_resolution(bidi_class);
516+
needs_bidi_resolution |= bidi::needs_bidi_resolution(bidi_class);
515517
// TODO: maybe extend Properties to u64 to fit BidiMirroringGlyph
516518
let bracket = lcx.analysis_data_sources.brackets().get(ch);
517519

parley/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
66
use alloc::{vec, vec::Vec};
77

8+
use parley_core::bidi::BidiResolver;
9+
810
use super::FontContext;
911
use super::builder::{RangedBuilder, StyleRunBuilder};
1012
use super::resolve::tree::TreeStyleBuilder;
1113
use super::resolve::{RangedStyleBuilder, ResolveContext, ResolvedStyle, StyleRun};
1214
use super::style::{Brush, TextStyle};
1315

1416
use crate::analysis::{AnalysisDataSources, CharInfo};
15-
use crate::bidi::BidiResolver;
1617
use crate::builder::TreeBuilder;
1718
use crate::inline_box::InlineBox;
1819
use crate::shape::ShapeContext;

parley/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ extern crate std;
109109
pub use fontique;
110110

111111
mod analysis;
112-
mod bidi;
113112
mod break_overrides;
114113
mod builder;
115114
mod context;

parley_core/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "parley_core"
3-
version = "0.0.0"
3+
version = "0.11.0"
44
description = "Parley Core provides low level APIs for implementing text layout."
55
keywords = ["text", "layout"]
66
categories = ["gui", "graphics"]
@@ -9,14 +9,15 @@ rust-version.workspace = true
99
license.workspace = true
1010
repository.workspace = true
1111

12-
publish = false
13-
1412
[package.metadata.docs.rs]
1513
all-features = true
1614

1715
[features]
1816
default = ["std"]
1917
std = []
2018

19+
[dependencies]
20+
icu_properties = { workspace = true, features = ["compiled_data"] }
21+
2122
[lints]
2223
workspace = true
Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ use alloc::vec::Vec;
77
use icu_properties::props::{BidiClass, BidiMirroringGlyph, BidiPairedBracketType};
88

99
/// Type alias for a bidirectional level.
10-
pub(crate) type BidiLevel = u8;
10+
pub type BidiLevel = u8;
1111

1212
/// Resolver for the Unicode bidirectional algorithm.
1313
#[derive(Clone, Default)]
14-
pub(crate) struct BidiResolver {
14+
pub struct BidiResolver {
1515
base_level: BidiLevel,
1616
levels: Vec<BidiLevel>,
1717
initial_types: Vec<BidiClass>,
@@ -23,9 +23,18 @@ pub(crate) struct BidiResolver {
2323
flags: u16,
2424
}
2525

26+
impl core::fmt::Debug for BidiResolver {
27+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
28+
f.debug_struct("BidiResolver")
29+
.field("base_level", &self.base_level)
30+
.field("levels", &self.levels)
31+
.finish_non_exhaustive()
32+
}
33+
}
34+
2635
impl BidiResolver {
2736
/// Creates a new resolver.
28-
pub(crate) fn new() -> Self {
37+
pub fn new() -> Self {
2938
Self {
3039
base_level: 0,
3140
levels: Vec::new(),
@@ -40,18 +49,18 @@ impl BidiResolver {
4049
}
4150

4251
/// Returns the base level of the text.
43-
pub(crate) fn base_level(&self) -> u8 {
52+
pub fn base_level(&self) -> u8 {
4453
self.base_level
4554
}
4655

4756
/// Returns the sequence of bidi levels corresponding to all characters in the
4857
/// paragraph.
49-
pub(crate) fn levels(&self) -> &[BidiLevel] {
58+
pub fn levels(&self) -> &[BidiLevel] {
5059
&self.levels
5160
}
5261

5362
/// Clears the resolver state.
54-
pub(crate) fn clear(&mut self) {
63+
pub fn clear(&mut self) {
5564
self.initial_types.clear();
5665
self.levels.clear();
5766
self.types.clear();
@@ -63,7 +72,7 @@ impl BidiResolver {
6372

6473
/// Resolves a paragraph with the specified base direction and
6574
/// precomputed types.
66-
pub(crate) fn resolve(
75+
pub fn resolve(
6776
&mut self,
6877
chars: impl Iterator<Item = (char, (BidiClass, BidiMirroringGlyph))>,
6978
base_level: Option<u8>,
@@ -240,8 +249,7 @@ impl BidiResolver {
240249
} else {
241250
(stack.embedding_level() + 2) & !1
242251
};
243-
if new_level <= MAX_STACK as u8 && overflow_isolates == 0 && overflow_embedding == 0
244-
{
252+
if new_level <= MAX_STACK && overflow_isolates == 0 && overflow_embedding == 0 {
245253
if is_isolate {
246254
valid_isolates += 1;
247255
}
@@ -387,7 +395,7 @@ impl BidiResolver {
387395
}
388396
}
389397

390-
#[allow(clippy::needless_range_loop)]
398+
#[expect(clippy::needless_range_loop, reason = "Deferred")]
391399
fn resolve_sequence(&mut self, level: u8, sos: BidiClass, eos: BidiClass, len: usize) {
392400
if len == 0 {
393401
return;
@@ -718,7 +726,7 @@ where
718726

719727
/// Returns whether the character needs bidirectional resolution.
720728
#[inline(always)]
721-
pub(crate) fn needs_bidi_resolution(bidi_class: BidiClass) -> bool {
729+
pub fn needs_bidi_resolution(bidi_class: BidiClass) -> bool {
722730
mask(bidi_class) & BIDI_MASK != 0
723731
}
724732

@@ -805,22 +813,22 @@ impl Run {
805813
}
806814
}
807815

808-
const MAX_STACK: usize = 125;
816+
const MAX_STACK: u8 = 125;
809817

810818
struct Stack {
811-
embedding_level: [u8; MAX_STACK + 1],
812-
override_status: [BidiClass; MAX_STACK + 1],
813-
isolate_status: [bool; MAX_STACK + 1],
819+
embedding_level: [u8; MAX_STACK as usize + 1],
820+
override_status: [BidiClass; MAX_STACK as usize + 1],
821+
isolate_status: [bool; MAX_STACK as usize + 1],
814822
depth: usize,
815823
}
816824

817825
impl Stack {
818826
fn new() -> Self {
819827
Self {
820828
depth: 0,
821-
embedding_level: [0; MAX_STACK + 1],
822-
override_status: [BidiClass::OtherNeutral; MAX_STACK + 1],
823-
isolate_status: [false; MAX_STACK + 1],
829+
embedding_level: [0; MAX_STACK as usize + 1],
830+
override_status: [BidiClass::OtherNeutral; MAX_STACK as usize + 1],
831+
isolate_status: [false; MAX_STACK as usize + 1],
824832
}
825833
}
826834

parley_core/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@
2020
#![no_std]
2121
#[cfg(feature = "std")]
2222
extern crate std;
23+
24+
extern crate alloc;
25+
26+
pub mod bidi;

0 commit comments

Comments
 (0)