Skip to content
Draft
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
13 changes: 13 additions & 0 deletions .agents/docs/attestations/2026-10-11-glyph-975230cb.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 2 additions & 19 deletions packages/glyph/rust/shaper/src/engine/cluster_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use crate::{FontGlyphExtents, FontMetrics, unicode::UnicodeAnalysis};
use super::{
EngineError, FrameFault,
frame::{WRAP_CHARACTER, WRAP_NONE, WRAP_WORD},
identity_index::{IdentityIndex, IdentityIndexError},
identity_index::{IdentityIndex, identity_index_error},
line_composition::Correction,
reserve_vec as reserve,
run_local::{NumericBlockSpan, RunLocalArena},
shaping_state::{ShapeArena, ShapingRun},
style_state::{ResolvedStyle, StyleArena, StyleSegment},
Expand Down Expand Up @@ -1975,15 +1976,6 @@ fn is_hard_break(text: &[u16], start: u32) -> Result<bool, EngineError> {
))
}

fn reserve<T>(values: &mut Vec<T>, capacity: usize) -> Result<(), EngineError> {
if values.capacity() < capacity {
values
.try_reserve_exact(capacity.saturating_sub(values.len()))
.map_err(|_| EngineError::ResultTooLarge)?;
}
Ok(())
}

/// True exactly when the build scatter's destination equals every glyph's own
/// index: the shaped runs tile the glyph array in array order and the source
/// cluster ids never decrease across it, so per-cluster ordinals assign
Expand Down Expand Up @@ -2398,15 +2390,6 @@ fn glyph_slice<T>(values: &[T], range: core::ops::Range<usize>) -> Result<&[T],
values.get(range).ok_or(EngineError::InvalidRequest)
}

fn identity_index_error(error: IdentityIndexError) -> EngineError {
match error {
IdentityIndexError::AllocationFailed | IdentityIndexError::ArithmeticOverflow => {
EngineError::ResultTooLarge
}
IdentityIndexError::DuplicateIdentity => EngineError::InvalidRequest,
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
12 changes: 3 additions & 9 deletions packages/glyph/rust/shaper/src/engine/flow_composition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ impl FlowLayoutArena {
self.clear();
return Ok(false);
}
let first_fragments = line_fragments(previous, line_index)?;
let first_fragments = previous.line_fragments(line_index)?;
let Some(first_fragment) = first_fragments.first() else {
self.clear();
return Ok(false);
Expand Down Expand Up @@ -1281,7 +1281,8 @@ impl FlowLayoutArena {
.iter()
.rposition(|line| line.flow_thread_id == constraint.flow_thread_id);
let cursor_start = if let Some(line_index) = previous_thread_line {
line_fragments(previous, line_index)?
previous
.line_fragments(line_index)?
.last()
.and_then(|fragment| usize::try_from(fragment.line.cluster_end).ok())
.ok_or(EngineError::InvalidRequest)?
Expand Down Expand Up @@ -2005,13 +2006,6 @@ fn shrink_for_flow_thread(
.ok_or(EngineError::InvalidRequest)
}

fn line_fragments(
flow: &FlowLayoutArena,
line_index: usize,
) -> Result<RopeRange<'_, FlowFragment>, EngineError> {
flow.line_fragments(line_index)
}

fn same_flow_line_records(
left_line: FlowLine,
left_fragments: &RopeRange<'_, FlowFragment>,
Expand Down
11 changes: 11 additions & 0 deletions packages/glyph/rust/shaper/src/engine/identity_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@

use alloc::vec::Vec;

use super::EngineError;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum IdentityIndexError {
AllocationFailed,
ArithmeticOverflow,
DuplicateIdentity,
}

pub(super) fn identity_index_error(error: IdentityIndexError) -> EngineError {
match error {
IdentityIndexError::AllocationFailed | IdentityIndexError::ArithmeticOverflow => {
EngineError::ResultTooLarge
}
IdentityIndexError::DuplicateIdentity => EngineError::InvalidRequest,
}
}

#[derive(Default)]
pub(crate) struct IdentityIndex {
keys: Vec<u32>,
Expand Down
11 changes: 11 additions & 0 deletions packages/glyph/rust/shaper/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//! The public types in this module are available to native consumers. Wasm memory ownership and
//! pointer validation stay in the target-gated transport module.

use alloc::vec::Vec;

mod cluster_state;
#[cfg_attr(not(test), allow(dead_code))]
mod flow_composition;
Expand Down Expand Up @@ -60,3 +62,12 @@ mod work_attribution;

pub(crate) use positioning::SemanticGlyph;
pub use state::{EngineError, FrameFault, TextEngine};

fn reserve_vec<T>(values: &mut Vec<T>, capacity: usize) -> Result<(), EngineError> {
if values.capacity() < capacity {
values
.try_reserve_exact(capacity.saturating_sub(values.len()))
.map_err(|_| EngineError::ResultTooLarge)?;
}
Ok(())
}
21 changes: 2 additions & 19 deletions packages/glyph/rust/shaper/src/engine/positioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ use super::{
codec_gather::{LayoutGlyph, PAINT_LAYER_GLYPH},
flow_composition::{FlowDropCap, FlowFragment, FlowLayoutArena, FlowLine},
frame::{ALIGN_CENTER, ALIGN_END, ALIGN_JUSTIFY, ALIGN_START},
identity_index::{IdentityIndex, IdentityIndexError},
identity_index::{IdentityIndex, identity_index_error},
line_composition::ComposedLine,
placement_slot_arena::PlacementHandle,
reserve_vec as reserve,
retained_rope::{RopeCursor, RopeCursorRange},
run_local::{
ClusterFinish, RunLocalArena, RunLocalBuildError, RunLocalGlyph, RunLocalGlyphInput,
Expand Down Expand Up @@ -4541,24 +4542,6 @@ fn nonnegative_f32(value: f64) -> Result<f32, EngineError> {
.ok_or(EngineError::InvalidRequest)
}

fn identity_index_error(error: IdentityIndexError) -> EngineError {
match error {
IdentityIndexError::AllocationFailed | IdentityIndexError::ArithmeticOverflow => {
EngineError::ResultTooLarge
}
IdentityIndexError::DuplicateIdentity => EngineError::InvalidRequest,
}
}

fn reserve<T>(values: &mut Vec<T>, capacity: usize) -> Result<(), EngineError> {
if values.capacity() < capacity {
values
.try_reserve_exact(capacity.saturating_sub(values.len()))
.map_err(|_| EngineError::ResultTooLarge)?;
}
Ok(())
}

#[cfg(test)]
mod tests {
use super::super::{
Expand Down
18 changes: 2 additions & 16 deletions packages/glyph/rust/shaper/src/engine/shaping_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};

use super::{
EngineError,
EngineError, reserve_vec,
style_state::{ResolvedStyle, StyleArena, StyleSegment},
};

Expand Down Expand Up @@ -92,12 +92,7 @@ pub(crate) struct BoundaryShapeArena {

impl ShapingRunArena {
pub(crate) fn reserve(&mut self, capacity: usize) -> Result<(), EngineError> {
if self.runs.capacity() < capacity {
self.runs
.try_reserve_exact(capacity.saturating_sub(self.runs.len()))
.map_err(|_| EngineError::ResultTooLarge)?;
}
Ok(())
reserve_vec(&mut self.runs, capacity)
}

pub(crate) fn build(
Expand Down Expand Up @@ -580,15 +575,6 @@ impl BoundaryShapeArena {
}
}

fn reserve_vec<T>(values: &mut Vec<T>, capacity: usize) -> Result<(), EngineError> {
if values.capacity() < capacity {
values
.try_reserve_exact(capacity.saturating_sub(values.len()))
.map_err(|_| EngineError::ResultTooLarge)?;
}
Ok(())
}

fn direction(style: ResolvedStyle, level: u8) -> u8 {
if style.bidi_override {
u8::from(style.direction == 2)
Expand Down
Loading