Skip to content

Commit

Permalink
Merge pull request #82 from kas-gui/work2
Browse files Browse the repository at this point in the history
Revisions: move status tracking and Env::* to Text, ...
  • Loading branch information
dhardy authored Mar 10, 2024
2 parents 16cc2f4 + 45a99af commit d9d2a99
Show file tree
Hide file tree
Showing 16 changed files with 848 additions and 681 deletions.
6 changes: 6 additions & 0 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ impl Vec2 {
pub fn max(self, other: Self) -> Self {
Vec2(self.0.max(other.0), self.1.max(other.1))
}

/// Whether both components are finite
#[inline]
pub fn is_finite(self) -> bool {
self.0.is_finite() && self.1.is_finite()
}
}

impl std::ops::Add for Vec2 {
Expand Down
68 changes: 29 additions & 39 deletions src/display/glyph_pos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#![allow(clippy::never_loop)]
#![allow(clippy::needless_range_loop)]

use super::{Line, NotReady, TextDisplay};
use super::{Line, TextDisplay};
use crate::conv::to_usize;
use crate::fonts::{fonts, FaceId};
use crate::fonts::{self, FaceId};
use crate::{Glyph, Vec2};

/// Effect formatting marker
Expand Down Expand Up @@ -143,6 +143,9 @@ impl ExactSizeIterator for MarkerPosIter {}
impl TextDisplay {
/// Find the starting position (top-left) of the glyph at the given index
///
/// [Requires status][Self#status-of-preparation]:
/// text is fully prepared for display.
///
/// The index should be no greater than the text length. It is not required
/// to be on a code-point boundary. Returns an iterator over matching
/// positions. Length of results is guaranteed to be one of 0, 1 or 2:
Expand All @@ -158,11 +161,7 @@ impl TextDisplay {
/// The result is not guaranteed to be within [`Self::bounding_box`].
/// Depending on the use-case, the caller may need to clamp the resulting
/// position.
pub fn text_glyph_pos(&self, index: usize) -> Result<MarkerPosIter, NotReady> {
if !self.action.is_ready() {
return Err(NotReady);
}

pub fn text_glyph_pos(&self, index: usize) -> MarkerPosIter {
let mut v: [MarkerPos; 2] = Default::default();
let (a, mut b) = (0, 0);
let mut push_result = |pos, ascent, descent, level| {
Expand All @@ -182,7 +181,7 @@ impl TextDisplay {
}

let glyph_run = &self.runs[to_usize(run_part.glyph_run)];
let sf = fonts()
let sf = fonts::library()
.get_face(glyph_run.face_id)
.scale_by_dpu(glyph_run.dpu);

Expand Down Expand Up @@ -230,11 +229,13 @@ impl TextDisplay {
break;
}

Ok(MarkerPosIter { v, a, b })
MarkerPosIter { v, a, b }
}

/// Get the number of glyphs
///
/// [Requires status][Self#status-of-preparation]: lines have been wrapped.
///
/// This method is a simple memory-read.
#[inline]
#[cfg_attr(doc_cfg, doc(cfg(feature = "num_glyphs")))]
Expand All @@ -245,29 +246,28 @@ impl TextDisplay {

/// Yield a sequence of positioned glyphs
///
/// [Requires status][Self#status-of-preparation]:
/// text is fully prepared for display.
///
/// Glyphs are yielded in undefined order by a call to `f`. The number of
/// glyphs yielded will equal [`TextDisplay::num_glyphs`]. The closure `f`
/// receives parameters `face_id, dpem, glyph`.
///
/// This may be used as follows:
/// ```no_run
/// # use kas_text::{Glyph, Text, Environment, TextApi, TextApiExt};
/// # use kas_text::{Glyph, Text, TextApi, TextApiExt, Vec2};
/// # fn draw(_: Vec<(f32, Glyph)>) {}
/// let mut text = Text::new("Some example text");
/// text.prepare();
///
/// let mut glyphs = Vec::with_capacity(text.num_glyphs());
/// let mut glyphs = Vec::with_capacity(text.num_glyphs().unwrap_or(0));
/// text.glyphs(|_, dpem, glyph| glyphs.push((dpem, glyph)));
/// draw(glyphs);
/// ```
///
/// This method has fairly low cost: `O(n)` in the number of glyphs with
/// low overhead.
pub fn glyphs<F: FnMut(FaceId, f32, Glyph)>(&self, mut f: F) -> Result<(), NotReady> {
if !self.action.is_ready() {
return Err(NotReady);
}

pub fn glyphs<F: FnMut(FaceId, f32, Glyph)>(&self, mut f: F) {
// self.wrapped_runs is in logical order
for run_part in self.wrapped_runs.iter().cloned() {
let run = &self.runs[to_usize(run_part.glyph_run)];
Expand All @@ -279,12 +279,13 @@ impl TextDisplay {
f(face_id, dpem, glyph);
}
}

Ok(())
}

/// Like [`TextDisplay::glyphs`] but with added effects
///
/// [Requires status][Self#status-of-preparation]:
/// text is fully prepared for display.
///
/// If the list `effects` is empty or has first entry with `start > 0`, the
/// result of `Effect::default(default_aux)` is used. The user payload of
/// type `X` is simply passed through to `f` and `g` calls and may be useful
Expand All @@ -311,17 +312,12 @@ impl TextDisplay {
default_aux: X,
mut f: F,
mut g: G,
) -> Result<(), NotReady>
where
) where
X: Copy,
F: FnMut(FaceId, f32, Glyph, usize, X),
G: FnMut(f32, f32, f32, f32, usize, X),
{
if !self.action.is_ready() {
return Err(NotReady);
}

let fonts = fonts();
let fonts = fonts::library();

let mut effect_cur = usize::MAX;
let mut effect_next = 0;
Expand Down Expand Up @@ -472,22 +468,15 @@ impl TextDisplay {
g(x1, x2, y_top, h, effect_cur, aux);
}
}

Ok(())
}

/// Yield a sequence of rectangles to highlight a given text range
///
/// [Requires status][Self#status-of-preparation]:
/// text is fully prepared for display.
///
/// Calls `f(top_left, bottom_right)` for each highlighting rectangle.
pub fn highlight_range(
&self,
range: std::ops::Range<usize>,
f: &mut dyn FnMut(Vec2, Vec2),
) -> Result<(), NotReady> {
if !self.action.is_ready() {
return Err(NotReady);
}

pub fn highlight_range(&self, range: std::ops::Range<usize>, f: &mut dyn FnMut(Vec2, Vec2)) {
for line in &self.lines {
let line_range: std::ops::Range<usize> = line.text_range.into();
if line_range.end <= range.start {
Expand All @@ -502,12 +491,13 @@ impl TextDisplay {
self.highlight_line(line.clone(), range.clone(), f);
}
}

Ok(())
}

/// Produce highlighting rectangles within a range of runs
///
/// [Requires status][Self#status-of-preparation]:
/// text is fully prepared for display.
///
/// Warning: runs are in logical order which does not correspond to display
/// order. As a result, the order of results (on a line) is not known.
fn highlight_line(
Expand All @@ -516,7 +506,7 @@ impl TextDisplay {
range: std::ops::Range<usize>,
f: &mut dyn FnMut(Vec2, Vec2),
) {
let fonts = fonts();
let fonts = fonts::library();

let mut a;

Expand Down
Loading

0 comments on commit d9d2a99

Please sign in to comment.