Skip to content
This repository has been archived by the owner on Nov 26, 2024. It is now read-only.

Commit

Permalink
#58 wip
Browse files Browse the repository at this point in the history
  • Loading branch information
bennobuilder committed Mar 22, 2024
1 parent c2736ac commit c96baed
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 15 deletions.
24 changes: 23 additions & 1 deletion crates/attributed_string/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,29 @@ impl AttributedString {
}

for line in lines.iter() {
// TODO
if line.get_span_ranges().is_empty() {
continue;
}

let mut pos = Vec2::new(0.0, 0.0);
let mut max_ascent: f32 = 0.0;
let mut max_descent: f32 = 0.0;

for span_range in line.get_span_ranges().iter() {
let span = &self.spans[span_range.index];
let attrs = &self.attrs_intervals.intervals[span.get_attrs_index()].val;
let font_size = attrs.get_font_size();

for glyph_token in span.iter_glyphs_in_range(line.get_range()) {
let advance = glyph_token.get_glyph().advance * font_size;

// glyph_token.set_transform(pos); // TODO

pos += advance;
max_ascent = max_ascent.max(glyph_token.get_glyph().ascent);
max_descent = max_descent.max(glyph_token.get_glyph().descent);
}
}
}

self.lines = lines;
Expand Down
12 changes: 9 additions & 3 deletions crates/attributed_string/src/tokens/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ use super::span::SpanToken;
#[derive(Debug, Clone)]
pub struct LineToken {
span_ranges: Vec<SpanRange>,
max_ascent: f32,
max_descent: f32,
}

impl LineToken {
pub fn new(mut span_ranges: Vec<SpanRange>) -> Self {
sort_span_ranges(&mut span_ranges);
Self { span_ranges }
Self {
span_ranges,
max_ascent: 0.0,
max_descent: 0.0,
}
}

pub fn get_range(&self) -> Range<usize> {
Expand Down Expand Up @@ -41,8 +47,8 @@ impl LineToken {

#[derive(Debug, Clone)]
pub struct SpanRange {
index: usize,
range: Range<usize>,
pub index: usize,
pub range: Range<usize>,
}

impl SpanRange {
Expand Down
12 changes: 12 additions & 0 deletions crates/attributed_string/src/tokens/shape/glyph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ impl GlyphToken {
bbox: Vec2::default(),
}
}

pub fn get_glyph(&self) -> &Glyph {
&self.glyph
}

pub fn get_transform(&self) -> &Vec2 {
&self.transform
}

pub fn set_transform(&mut self, transform: Vec2) {
self.transform = transform;
}
}

impl ShapeToken for GlyphToken {
Expand Down
50 changes: 39 additions & 11 deletions crates/attributed_string/src/tokens/span.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::shape::{
glyph::GlyphToken, linebreak::LinebreakToken, text_fragment::TextFragmentToken,
word_separator::WordSeparatorToken, ShapeBuffer, ShapeTokenVariant,
word_separator::WordSeparatorToken, ShapeBuffer, ShapeToken, ShapeTokenVariant,
};
use crate::{attrs::Attrs, fonts_cache::FontsCache};
use glam::Vec2;
Expand Down Expand Up @@ -152,7 +152,12 @@ impl SpanToken {

#[inline]
pub fn iter_glyphs(&self) -> GlyphTokenRefIterator {
GlyphTokenRefIterator::new(self)
GlyphTokenRefIterator::new(self, self.range.clone())
}

#[inline]
pub fn iter_glyphs_in_range(&self, range: Range<usize>) -> GlyphTokenRefIterator {
GlyphTokenRefIterator::new(self, range)
}
}

Expand All @@ -162,16 +167,23 @@ pub struct GlyphTokenRefIterator<'a> {
token_index: usize,
// Tracks the position within the current ShapeTokenVariant's GlyphToken vector
glyph_index: usize,
// The range of interest for yielding GlyphTokens
range: Range<usize>,
}

impl<'a> GlyphTokenRefIterator<'a> {
pub fn new(span_token: &'a SpanToken) -> Self {
pub fn new(span_token: &'a SpanToken, range: Range<usize>) -> Self {
Self {
span_token,
token_index: 0,
glyph_index: 0,
range,
}
}

fn is_within_range(&self, token_range: &Range<usize>) -> bool {
self.range.start <= token_range.start && token_range.end <= self.range.end
}
}

impl<'a> Iterator for GlyphTokenRefIterator<'a> {
Expand All @@ -180,34 +192,50 @@ impl<'a> Iterator for GlyphTokenRefIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
while self.token_index < self.span_token.tokens.len() {
match &self.span_token.tokens[self.token_index] {
// Move to next token after yielding a Glyph
// Move to next token after yielding a glyph
ShapeTokenVariant::Glyph(glyph) if self.glyph_index == 0 => {
self.token_index += 1;
return Some(glyph);
if self.is_within_range(glyph.get_range()) {
return Some(glyph);
}
}
ShapeTokenVariant::WordSeparator(token)
if self.glyph_index < token.get_tokens().len() =>
{
let glyph = &token.get_tokens()[self.glyph_index];
self.glyph_index += 1;
if self.glyph_index == token.get_tokens().len() {

if self.is_within_range(token.get_range()) {
self.glyph_index += 1;
if self.glyph_index == token.get_tokens().len() {
// Reset glyph_index and move to next token for next call
self.glyph_index = 0;
self.token_index += 1;
}
return Some(glyph);
} else {
// Reset glyph_index and move to next token for next call
self.glyph_index = 0;
self.token_index += 1;
}
return Some(glyph);
}
ShapeTokenVariant::TextFragment(token)
if self.glyph_index < token.get_tokens().len() =>
{
let glyph = &token.get_tokens()[self.glyph_index];
self.glyph_index += 1;
if self.glyph_index == token.get_tokens().len() {

if self.is_within_range(token.get_range()) {
self.glyph_index += 1;
if self.glyph_index == token.get_tokens().len() {
// Reset glyph_index and move to next token for next call
self.glyph_index = 0;
self.token_index += 1;
}
return Some(glyph);
} else {
// Reset glyph_index and move to next token for next call
self.glyph_index = 0;
self.token_index += 1;
}
return Some(glyph);
}
// For non-glyph-carrying tokens or if no more glyphs in current token, move to the next one
_ => {
Expand Down

0 comments on commit c96baed

Please sign in to comment.