55
66//! Parsers for formatted text
77
8+ use crate :: Effect ;
89use crate :: fonts:: FontSelector ;
9- use crate :: { Effect , OwningVecIter } ;
1010#[ allow( unused) ]
1111use crate :: { Text , TextDisplay } ; // for doc-links
1212
@@ -18,14 +18,7 @@ mod markdown;
1818pub use markdown:: { Error as MarkdownError , Markdown } ;
1919
2020/// Text, optionally with formatting data
21- ///
22- /// Any `F: FormattableText` automatically support [`FormattableTextDyn`].
23- /// Implement either this or [`FormattableTextDyn`], not both.
24- pub trait FormattableText : std:: cmp:: PartialEq + std:: fmt:: Debug {
25- type FontTokenIter < ' a > : Iterator < Item = FontToken >
26- where
27- Self : ' a ;
28-
21+ pub trait FormattableText : std:: cmp:: PartialEq {
2922 /// Length of text
3023 ///
3124 /// Default implementation uses [`FormattableText::as_str`].
@@ -37,148 +30,53 @@ pub trait FormattableText: std::cmp::PartialEq + std::fmt::Debug {
3730 /// Access whole text as contiguous `str`
3831 fn as_str ( & self ) -> & str ;
3932
40- /// Construct an iterator over formatting items
33+ /// Return an iterator of font tokens
4134 ///
42- /// It is expected that [`FontToken::start`] of yielded items is strictly
43- /// increasing; if not, formatting may not be applied correctly.
35+ /// These tokens are used to select the font and font size.
36+ /// Each text object has a configured
37+ /// [font size][crate::Text::set_font_size] and [`FontSelector`]; these
38+ /// values are passed as a reference (`dpem` and `font`).
4439 ///
45- /// The default [font size][crate::Text::set_font_size] (`dpem`) is passed
46- /// as a reference.
40+ /// The iterator is expected to yield a stream of tokens such that
41+ /// [`FontToken::start`] values are strictly increasing, less than
42+ /// [`Self::str_len`] and at `char` boundaries (i.e. an index value returned
43+ /// by [`str::char_indices`]. In case the returned iterator is empty or the
44+ /// first [`FontToken::start`] value is greater than zero the reference
45+ /// `dpem` and `font` values are used.
4746 ///
48- /// For plain text this iterator will be empty.
49- fn font_tokens < ' a > ( & ' a self , dpem : f32 ) -> Self :: FontTokenIter < ' a > ;
47+ /// Any changes to the result of this method require full re-preparation of
48+ /// text since this affects run breaking and font resolution.
49+ fn font_tokens ( & self , dpem : f32 , font : FontSelector ) -> impl Iterator < Item = FontToken > ;
5050
51- /// Get the sequence of effect tokens
51+ /// Return the sequence of effect tokens
52+ ///
53+ /// These tokens are used to select the font color and
54+ /// [effects](crate::EffectFlags).
5255 ///
53- /// This method has some limitations: (1) it may only return a reference to
54- /// an existing sequence, (2) effect tokens cannot be generated dependent
55- /// on input state, and (3) it does not incorporate color information. For
56- /// most uses it should still be sufficient, but for other cases it may be
57- /// preferable not to use this method (use a dummy implementation returning
58- /// `&[]` and use inherent methods on the text object via [`Text::text`]).
56+ /// The values of [`Effect::start`] are expected to be strictly increasing
57+ /// in order, less than [`Self::str_len`]. In case the slice is empty or the
58+ /// first [`Effect::start`] value is greater than zero, values from
59+ /// [`Effect::default()`] are used.
60+ ///
61+ /// Changes to the result of this method do not require any re-preparation
62+ /// of text.
5963 fn effect_tokens ( & self ) -> & [ Effect ] ;
6064}
6165
6266impl < F : FormattableText + ?Sized > FormattableText for & F {
63- type FontTokenIter < ' a >
64- = F :: FontTokenIter < ' a >
65- where
66- Self : ' a ;
67-
6867 fn as_str ( & self ) -> & str {
6968 F :: as_str ( self )
7069 }
7170
72- fn font_tokens < ' a > ( & ' a self , dpem : f32 ) -> Self :: FontTokenIter < ' a > {
73- F :: font_tokens ( self , dpem)
71+ fn font_tokens ( & self , dpem : f32 , font : FontSelector ) -> impl Iterator < Item = FontToken > {
72+ F :: font_tokens ( self , dpem, font )
7473 }
7574
7675 fn effect_tokens ( & self ) -> & [ Effect ] {
7776 F :: effect_tokens ( self )
7877 }
7978}
8079
81- /// Text, optionally with formatting data
82- ///
83- /// This is an object-safe version of the [`FormattableText`] trait (i.e.
84- /// `dyn FormattableTextDyn` is a valid type).
85- ///
86- /// This trait is auto-implemented for every implementation of [`FormattableText`].
87- /// The type `&dyn FormattableTextDyn` implements [`FormattableText`].
88- /// Implement either this or (preferably) [`FormattableText`], not both.
89- pub trait FormattableTextDyn : std:: fmt:: Debug {
90- /// Produce a boxed clone of self
91- fn clone_boxed ( & self ) -> Box < dyn FormattableTextDyn > ;
92-
93- /// Length of text
94- fn str_len ( & self ) -> usize ;
95-
96- /// Access whole text as contiguous `str`
97- fn as_str ( & self ) -> & str ;
98-
99- /// Construct an iterator over formatting items
100- ///
101- /// It is expected that [`FontToken::start`] of yielded items is strictly
102- /// increasing; if not, formatting may not be applied correctly.
103- ///
104- /// The default [font size][crate::Text::set_font_size] (`dpem`) is passed
105- /// as a reference.
106- ///
107- /// For plain text this iterator will be empty.
108- fn font_tokens ( & self , dpem : f32 ) -> OwningVecIter < FontToken > ;
109-
110- /// Get the sequence of effect tokens
111- ///
112- /// This method has some limitations: (1) it may only return a reference to
113- /// an existing sequence, (2) effect tokens cannot be generated dependent
114- /// on input state, and (3) it does not incorporate color information. For
115- /// most uses it should still be sufficient, but for other cases it may be
116- /// preferable not to use this method (use a dummy implementation returning
117- /// `&[]` and use inherent methods on the text object via [`Text::text`]).
118- fn effect_tokens ( & self ) -> & [ Effect ] ;
119- }
120-
121- impl < F : FormattableText + Clone + ' static > FormattableTextDyn for F {
122- fn clone_boxed ( & self ) -> Box < dyn FormattableTextDyn > {
123- Box :: new ( self . clone ( ) )
124- }
125-
126- fn str_len ( & self ) -> usize {
127- FormattableText :: str_len ( self )
128- }
129- fn as_str ( & self ) -> & str {
130- FormattableText :: as_str ( self )
131- }
132-
133- fn font_tokens ( & self , dpem : f32 ) -> OwningVecIter < FontToken > {
134- let iter = FormattableText :: font_tokens ( self , dpem) ;
135- OwningVecIter :: new ( iter. collect ( ) )
136- }
137-
138- fn effect_tokens ( & self ) -> & [ Effect ] {
139- FormattableText :: effect_tokens ( self )
140- }
141- }
142-
143- /// References to [`FormattableTextDyn`] always compare unequal
144- impl < ' t > PartialEq for & ' t dyn FormattableTextDyn {
145- fn eq ( & self , _: & Self ) -> bool {
146- false
147- }
148- }
149-
150- impl < ' t > FormattableText for & ' t dyn FormattableTextDyn {
151- type FontTokenIter < ' a >
152- = OwningVecIter < FontToken >
153- where
154- Self : ' a ;
155-
156- #[ inline]
157- fn str_len ( & self ) -> usize {
158- FormattableTextDyn :: str_len ( * self )
159- }
160-
161- #[ inline]
162- fn as_str ( & self ) -> & str {
163- FormattableTextDyn :: as_str ( * self )
164- }
165-
166- #[ inline]
167- fn font_tokens ( & self , dpem : f32 ) -> OwningVecIter < FontToken > {
168- FormattableTextDyn :: font_tokens ( * self , dpem)
169- }
170-
171- fn effect_tokens ( & self ) -> & [ Effect ] {
172- FormattableTextDyn :: effect_tokens ( * self )
173- }
174- }
175-
176- impl Clone for Box < dyn FormattableTextDyn > {
177- fn clone ( & self ) -> Self {
178- ( * * self ) . clone_boxed ( )
179- }
180- }
181-
18280/// Font formatting token
18381#[ derive( Clone , Debug , PartialEq ) ]
18482pub struct FontToken {
0 commit comments