Skip to content

Commit 0bc2629

Browse files
authored
Merge pull request #99 from kas-gui/push-xwvsnqwxlrot
Replace Effect::aux with e; merge fns runs, runs_with_effects
2 parents 8918490 + 4cc4985 commit 0bc2629

File tree

7 files changed

+86
-131
lines changed

7 files changed

+86
-131
lines changed

src/display/glyph_pos.rs

Lines changed: 38 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,25 @@ use crate::fonts::{self, FaceId};
1616
use crate::{shaper, Glyph, Range, Vec2};
1717

1818
/// Effect formatting marker
19-
#[derive(Clone, Debug, PartialEq, Eq)]
19+
#[derive(Clone, Debug, Default, PartialEq, Eq)]
2020
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21-
pub struct Effect<X> {
21+
pub struct Effect {
2222
/// Index in text at which formatting becomes active
2323
///
2424
/// (Note that we use `u32` not `usize` since it can be assumed text length
2525
/// will never exceed `u32::MAX`.)
2626
pub start: u32,
27+
/// User-specified value, e.g. index into a colour palette
28+
pub e: u16,
2729
/// Effect flags
2830
pub flags: EffectFlags,
29-
/// User payload
30-
pub aux: X,
31-
}
32-
33-
impl<X> Effect<X> {
34-
/// Construct a "default" instance with the supplied `aux` value
35-
pub fn default(aux: X) -> Self {
36-
Effect {
37-
start: 0,
38-
flags: EffectFlags::empty(),
39-
aux,
40-
}
41-
}
4231
}
4332

4433
bitflags::bitflags! {
4534
/// Text effects
4635
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4736
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48-
pub struct EffectFlags: u32 {
37+
pub struct EffectFlags: u16 {
4938
/// Glyph is underlined
5039
const UNDERLINE = 1 << 0;
5140
/// Glyph is crossed through by a center-line
@@ -143,15 +132,14 @@ impl ExactSizeIterator for MarkerPosIter {}
143132
/// A sequence of positioned glyphs with effects
144133
///
145134
/// Yielded by [`TextDisplay::runs`] and [`TextDisplay::runs_with_effects`].
146-
pub struct GlyphRun<'a, X: Copy> {
135+
pub struct GlyphRun<'a> {
147136
run: &'a shaper::GlyphRun,
148137
range: Range,
149138
offset: Vec2,
150-
effects: &'a [Effect<X>],
151-
default_aux: X,
139+
effects: &'a [Effect],
152140
}
153141

154-
impl<'a, X: Copy> GlyphRun<'a, X> {
142+
impl<'a> GlyphRun<'a> {
155143
/// Get the font face used for this run
156144
#[inline]
157145
pub fn face_id(&self) -> FaceId {
@@ -182,25 +170,22 @@ impl<'a, X: Copy> GlyphRun<'a, X> {
182170

183171
/// Yield glyphs and effects for this run
184172
///
185-
/// The callback `f` receives `glyph, i, aux` where
186-
/// `dpu` and `height` are both measures of the font size (pixels per font
187-
/// unit and pixels per height, respectively), and `i` is the index within
188-
/// `effects` (or `usize::MAX` when a default-constructed effect token is
189-
/// used).
173+
/// The callback `f` receives `glyph, e` where `e` is the [`Effect::e`]
174+
/// value (defaults to 0).
190175
///
191176
/// The callback `g` receives positioning for each underline/strike-through
192177
/// segment: `x1, x2, y_top, h` where `h` is the thickness (height). Note
193178
/// that it is possible to have `h < 1.0` and `y_top, y_top + h` to round to
194179
/// the same number; the renderer is responsible for ensuring such lines
195-
/// are actually visible. The last parameters are `i, aux` as for `f`.
180+
/// are actually visible. The last parameter is `e` as for `f`.
196181
///
197182
/// Note: this is more computationally expensive than [`GlyphRun::glyphs`],
198183
/// so you may prefer to call that. Optionally one may choose to cache the
199184
/// result, though this is not really necessary.
200185
pub fn glyphs_with_effects<F, G>(&self, mut f: F, mut g: G)
201186
where
202-
F: FnMut(Glyph, usize, X),
203-
G: FnMut(f32, f32, f32, f32, usize, X),
187+
F: FnMut(Glyph, u16),
188+
G: FnMut(f32, f32, f32, f32, u16),
204189
{
205190
let sf = fonts::library()
206191
.get_face(self.run.face_id)
@@ -237,9 +222,7 @@ impl<'a, X: Copy> GlyphRun<'a, X> {
237222
.effects
238223
.get(effect_cur)
239224
.cloned()
240-
.unwrap_or(Effect::default(self.default_aux));
241-
242-
let mut effect_i = effect_cur;
225+
.unwrap_or(Effect::default());
243226

244227
// In case an effect applies to the left-most glyph, it starts from that
245228
// glyph's x coordinate.
@@ -251,15 +234,15 @@ impl<'a, X: Copy> GlyphRun<'a, X> {
251234
let y_top = position.1 - metrics.position;
252235
let h = metrics.thickness;
253236
let x1 = position.0;
254-
underline = Some((x1, y_top, h, fmt.aux));
237+
underline = Some((x1, y_top, h, fmt.e));
255238
}
256239
}
257240
if fmt.flags.contains(EffectFlags::STRIKETHROUGH) {
258241
if let Some(metrics) = sf.strikethrough_metrics() {
259242
let y_top = position.1 - metrics.position;
260243
let h = metrics.thickness;
261244
let x1 = position.0;
262-
strikethrough = Some((x1, y_top, h, fmt.aux));
245+
strikethrough = Some((x1, y_top, h, fmt.e));
263246
}
264247
}
265248
}
@@ -303,55 +286,53 @@ impl<'a, X: Copy> GlyphRun<'a, X> {
303286
.effects
304287
.get(effect_cur)
305288
.cloned()
306-
.unwrap_or(Effect::default(self.default_aux));
289+
.unwrap_or(Effect::default());
307290

308291
if underline.is_some() != fmt.flags.contains(EffectFlags::UNDERLINE) {
309-
if let Some((x1, y_top, h, aux)) = underline {
292+
if let Some((x1, y_top, h, e)) = underline {
310293
let x2 = glyph.position.0;
311-
g(x1, x2, y_top, h, effect_i, aux);
294+
g(x1, x2, y_top, h, e);
312295
underline = None;
313296
} else if let Some(metrics) = sf.underline_metrics() {
314297
let y_top = glyph.position.1 - metrics.position;
315298
let h = metrics.thickness;
316299
let x1 = glyph.position.0;
317-
underline = Some((x1, y_top, h, fmt.aux));
300+
underline = Some((x1, y_top, h, fmt.e));
318301
}
319302
}
320303
if strikethrough.is_some() != fmt.flags.contains(EffectFlags::STRIKETHROUGH) {
321-
if let Some((x1, y_top, h, aux)) = strikethrough {
304+
if let Some((x1, y_top, h, e)) = strikethrough {
322305
let x2 = glyph.position.0;
323-
g(x1, x2, y_top, h, effect_i, aux);
306+
g(x1, x2, y_top, h, e);
324307
strikethrough = None;
325308
} else if let Some(metrics) = sf.strikethrough_metrics() {
326309
let y_top = glyph.position.1 - metrics.position;
327310
let h = metrics.thickness;
328311
let x1 = glyph.position.0;
329-
strikethrough = Some((x1, y_top, h, fmt.aux));
312+
strikethrough = Some((x1, y_top, h, fmt.e));
330313
}
331314
}
332-
333-
effect_i = effect_cur;
334315
}
335316

336-
f(glyph, effect_cur, fmt.aux);
317+
f(glyph, fmt.e);
337318
}
338319

339320
// Effects end at the following glyph's start (or end of this run part)
340-
if let Some((x1, y_top, h, aux)) = underline {
321+
if let Some((x1, y_top, h, e)) = underline {
341322
let x2 = if self.range.end() < self.run.glyphs.len() {
342323
self.run.glyphs[self.range.end()].position.0
343324
} else {
344325
self.run.caret
345326
} + self.offset.0;
346-
g(x1, x2, y_top, h, effect_i, aux);
327+
g(x1, x2, y_top, h, e);
347328
}
348-
if let Some((x1, y_top, h, aux)) = strikethrough {
329+
if let Some((x1, y_top, h, e)) = strikethrough {
349330
let x2 = if self.range.end() < self.run.glyphs.len() {
350331
self.run.glyphs[self.range.end()].position.0
351332
} else {
352333
self.run.caret
353334
} + self.offset.0;
354-
g(x1, x2, y_top, h, effect_i, aux);
335+
g(x1, x2, y_top, h, e);
355336
}
356337
}
357338
}
@@ -461,43 +442,31 @@ impl TextDisplay {
461442

462443
/// Iterate over runs of positioned glyphs
463444
///
464-
/// This method is just sugar for `self.runs_with_effects(&[], ())`.
445+
/// All glyphs are translated by the given `offset` (this is practically
446+
/// free).
465447
///
466-
/// [Requires status][Self#status-of-preparation]:
467-
/// text is fully prepared for display.
448+
/// An [`Effect`] sequence supports underline, strikethrough and custom
449+
/// indexing (e.g. for a color palette). Pass `&[]` if effects are not
450+
/// required. (The default effect is always [`Effect::default()`].)
468451
///
469452
/// Runs are yielded in undefined order. The total number of
470453
/// glyphs yielded will equal [`TextDisplay::num_glyphs`].
471-
pub fn runs(&self) -> impl Iterator<Item = GlyphRun<'_, ()>> {
472-
self.runs_with_effects(&[], ())
473-
}
474-
475-
/// Iterate over runs of positioned glyphs with effects
476-
///
477-
/// If the list `effects` is empty or has first entry with `start > 0`, the
478-
/// result of `Effect::default(default_aux)` is used. The user payload of
479-
/// type `X` is simply passed through to `f` and `g` calls and may be useful
480-
/// for color information.
481454
///
482455
/// [Requires status][Self#status-of-preparation]:
483456
/// text is fully prepared for display.
484-
///
485-
/// Runs are yielded in undefined order. The total number of
486-
/// glyphs yielded will equal [`TextDisplay::num_glyphs`].
487-
pub fn runs_with_effects<'a, X: Copy>(
457+
pub fn runs<'a>(
488458
&'a self,
489-
effects: &'a [Effect<X>],
490-
default_aux: X,
491-
) -> impl Iterator<Item = GlyphRun<'a, X>> + 'a {
459+
offset: Vec2,
460+
effects: &'a [Effect],
461+
) -> impl Iterator<Item = GlyphRun<'a>> + 'a {
492462
self.wrapped_runs
493463
.iter()
494464
.filter(|part| !part.glyph_range.is_empty())
495465
.map(move |part| GlyphRun {
496466
run: &self.runs[to_usize(part.glyph_run)],
497467
range: part.glyph_range,
498-
offset: part.offset,
468+
offset: offset + part.offset,
499469
effects,
500-
default_aux,
501470
})
502471
}
503472

src/display/text_runs.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,10 @@ impl TextDisplay {
140140
let mut last_is_htab = false;
141141
let mut non_control_end = 0;
142142

143-
for (pos, c) in text.char_indices() {
143+
for (index, c) in text.char_indices() {
144144
// Handling for control chars
145145
if !last_is_control {
146-
non_control_end = pos;
146+
non_control_end = index;
147147
}
148148
let is_control = c.is_control();
149149
let is_htab = c == '\t';
@@ -158,10 +158,10 @@ impl TextDisplay {
158158
let is_break = hard_break || boundary == Boundary::Line;
159159

160160
// Force end of current run?
161-
let bidi_break = levels[pos] != input.level;
161+
let bidi_break = levels[index] != input.level;
162162

163163
if let Some(fmt) = next_fmt.as_ref() {
164-
if to_usize(fmt.start) == pos {
164+
if to_usize(fmt.start) == index {
165165
font = fmt.font;
166166
dpem = fmt.dpem;
167167
next_fmt = font_tokens.next();
@@ -173,7 +173,7 @@ impl TextDisplay {
173173
}
174174

175175
let opt_last_face = if matches!(
176-
classes[pos],
176+
classes[index],
177177
BidiClass::L | BidiClass::R | BidiClass::AL | BidiClass::EN | BidiClass::AN
178178
) {
179179
None
@@ -205,15 +205,15 @@ impl TextDisplay {
205205
self.runs
206206
.push(shaper::shape(input, range, face, breaks, special));
207207

208-
start = pos;
209-
non_control_end = pos;
210-
input.level = levels[pos];
208+
start = index;
209+
non_control_end = index;
210+
input.level = levels[index];
211211
breaks = Default::default();
212212
input.script = UNKNOWN_SCRIPT;
213213
} else if is_break && !is_control {
214214
// We do break runs when hitting control chars, but only when
215215
// encountering the next non-control character.
216-
breaks.push(shaper::GlyphBreak::new(to_u32(pos)));
216+
breaks.push(shaper::GlyphBreak::new(to_u32(index)));
217217
}
218218

219219
last_is_control = is_control;

src/format.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub trait FormattableText: std::cmp::PartialEq + std::fmt::Debug {
5656
/// most uses it should still be sufficient, but for other cases it may be
5757
/// preferable not to use this method (use a dummy implementation returning
5858
/// `&[]` and use inherent methods on the text object via [`Text::text`]).
59-
fn effect_tokens(&self) -> &[Effect<()>];
59+
fn effect_tokens(&self) -> &[Effect];
6060
}
6161

6262
impl<F: FormattableText + ?Sized> FormattableText for &F {
@@ -73,7 +73,7 @@ impl<F: FormattableText + ?Sized> FormattableText for &F {
7373
F::font_tokens(self, dpem)
7474
}
7575

76-
fn effect_tokens(&self) -> &[Effect<()>] {
76+
fn effect_tokens(&self) -> &[Effect] {
7777
F::effect_tokens(self)
7878
}
7979
}
@@ -115,7 +115,7 @@ pub trait FormattableTextDyn: std::fmt::Debug {
115115
/// most uses it should still be sufficient, but for other cases it may be
116116
/// preferable not to use this method (use a dummy implementation returning
117117
/// `&[]` and use inherent methods on the text object via [`Text::text`]).
118-
fn effect_tokens(&self) -> &[Effect<()>];
118+
fn effect_tokens(&self) -> &[Effect];
119119
}
120120

121121
impl<F: FormattableText + Clone + 'static> FormattableTextDyn for F {
@@ -135,7 +135,7 @@ impl<F: FormattableText + Clone + 'static> FormattableTextDyn for F {
135135
OwningVecIter::new(iter.collect())
136136
}
137137

138-
fn effect_tokens(&self) -> &[Effect<()>] {
138+
fn effect_tokens(&self) -> &[Effect] {
139139
FormattableText::effect_tokens(self)
140140
}
141141
}
@@ -168,7 +168,7 @@ impl<'t> FormattableText for &'t dyn FormattableTextDyn {
168168
FormattableTextDyn::font_tokens(*self, dpem)
169169
}
170170

171-
fn effect_tokens(&self) -> &[Effect<()>] {
171+
fn effect_tokens(&self) -> &[Effect] {
172172
FormattableTextDyn::effect_tokens(*self)
173173
}
174174
}

src/format/markdown.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub enum Error {
4949
pub struct Markdown {
5050
text: String,
5151
fmt: Vec<Fmt>,
52-
effects: Vec<Effect<()>>,
52+
effects: Vec<Effect>,
5353
}
5454

5555
impl Markdown {
@@ -118,7 +118,7 @@ impl FormattableText for Markdown {
118118
FontTokenIter::new(&self.fmt, dpem)
119119
}
120120

121-
fn effect_tokens(&self) -> &[Effect<()>] {
121+
fn effect_tokens(&self) -> &[Effect] {
122122
&self.effects
123123
}
124124
}
@@ -197,8 +197,8 @@ fn parse(input: &str) -> Result<Markdown, Error> {
197197
if token.flags != flags {
198198
effects.push(Effect {
199199
start: token.start,
200+
e: 0,
200201
flags: token.flags,
201-
aux: (),
202202
});
203203
flags = token.flags;
204204
}

src/format/plain.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl FormattableText for str {
2222
std::iter::empty()
2323
}
2424

25-
fn effect_tokens(&self) -> &[Effect<()>] {
25+
fn effect_tokens(&self) -> &[Effect] {
2626
&[]
2727
}
2828
}
@@ -38,7 +38,7 @@ impl FormattableText for String {
3838
std::iter::empty()
3939
}
4040

41-
fn effect_tokens(&self) -> &[Effect<()>] {
41+
fn effect_tokens(&self) -> &[Effect] {
4242
&[]
4343
}
4444
}

0 commit comments

Comments
 (0)