1#[cfg(not(feature = "std"))]
4use alloc::{
5 string::{String, ToString},
6 vec::Vec,
7};
8
9#[cfg(feature = "swash")]
10use std::cmp;
11
12use unicode_segmentation::UnicodeSegmentation;
13
14#[cfg(feature = "swash")]
15use crate::Color;
16use crate::{
17 Action, Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, BufferRef, Change, ChangeItem,
18 Cursor, Edit, FontSystem, LayoutRun, LineEnding, LineIter, Selection, Shaping,
19};
20
21#[derive(Debug, Clone)]
23pub struct Editor<'buffer> {
24 buffer_ref: BufferRef<'buffer>,
25 cursor: Cursor,
26 cursor_x_opt: Option<i32>,
27 selection: Selection,
28 cursor_moved: bool,
29 auto_indent: bool,
30 change: Option<Change>,
31}
32
33fn cursor_glyph_opt(cursor: &Cursor, run: &LayoutRun) -> Option<(usize, f32)> {
34 if cursor.line == run.line_i {
35 for (glyph_i, glyph) in run.glyphs.iter().enumerate() {
36 if cursor.index == glyph.start {
37 return Some((glyph_i, 0.0));
38 } else if cursor.index > glyph.start && cursor.index < glyph.end {
39 let mut before = 0;
41 let mut total = 0;
42
43 let cluster = &run.text[glyph.start..glyph.end];
44 for (i, _) in cluster.grapheme_indices(true) {
45 if glyph.start + i < cursor.index {
46 before += 1;
47 }
48 total += 1;
49 }
50
51 let offset = glyph.w * (before as f32) / (total as f32);
52 return Some((glyph_i, offset));
53 }
54 }
55 match run.glyphs.last() {
56 Some(glyph) => {
57 if cursor.index == glyph.end {
58 return Some((run.glyphs.len(), 0.0));
59 }
60 }
61 None => {
62 return Some((0, 0.0));
63 }
64 }
65 }
66 None
67}
68
69fn cursor_position(cursor: &Cursor, run: &LayoutRun) -> Option<(i32, i32)> {
70 let (cursor_glyph, cursor_glyph_offset) = cursor_glyph_opt(cursor, run)?;
71 let x = run.glyphs.get(cursor_glyph).map_or_else(
72 || {
73 run.glyphs.last().map_or(0, |glyph| {
74 if glyph.level.is_rtl() {
75 glyph.x as i32
76 } else {
77 (glyph.x + glyph.w) as i32
78 }
79 })
80 },
81 |glyph| {
82 if glyph.level.is_rtl() {
83 (glyph.x + glyph.w - cursor_glyph_offset) as i32
84 } else {
85 (glyph.x + cursor_glyph_offset) as i32
86 }
87 },
88 );
89
90 Some((x, run.line_top as i32))
91}
92
93impl<'buffer> Editor<'buffer> {
94 pub fn new(buffer: impl Into<BufferRef<'buffer>>) -> Self {
96 Self {
97 buffer_ref: buffer.into(),
98 cursor: Cursor::default(),
99 cursor_x_opt: None,
100 selection: Selection::None,
101 cursor_moved: false,
102 auto_indent: false,
103 change: None,
104 }
105 }
106
107 #[cfg(feature = "swash")]
109 #[allow(clippy::too_many_arguments)]
110 pub fn draw<F>(
111 &self,
112 font_system: &mut FontSystem,
113 cache: &mut crate::SwashCache,
114 text_color: Color,
115 cursor_color: Color,
116 selection_color: Color,
117 selected_text_color: Color,
118 mut f: F,
119 ) where
120 F: FnMut(i32, i32, u32, u32, Color),
121 {
122 let selection_bounds = self.selection_bounds();
123 self.with_buffer(|buffer| {
124 for run in buffer.layout_runs() {
125 let line_i = run.line_i;
126 let line_y = run.line_y;
127 let line_top = run.line_top;
128 let line_height = run.line_height;
129
130 if let Some((start, end)) = selection_bounds {
132 if line_i >= start.line && line_i <= end.line {
133 let mut range_opt = None;
134 for glyph in run.glyphs {
135 let cluster = &run.text[glyph.start..glyph.end];
137 let total = cluster.grapheme_indices(true).count();
138 let mut c_x = glyph.x;
139 let c_w = glyph.w / total as f32;
140 for (i, c) in cluster.grapheme_indices(true) {
141 let c_start = glyph.start + i;
142 let c_end = glyph.start + i + c.len();
143 if (start.line != line_i || c_end > start.index)
144 && (end.line != line_i || c_start < end.index)
145 {
146 range_opt = match range_opt.take() {
147 Some((min, max)) => Some((
148 cmp::min(min, c_x as i32),
149 cmp::max(max, (c_x + c_w) as i32),
150 )),
151 None => Some((c_x as i32, (c_x + c_w) as i32)),
152 };
153 } else if let Some((min, max)) = range_opt.take() {
154 f(
155 min,
156 line_top as i32,
157 cmp::max(0, max - min) as u32,
158 line_height as u32,
159 selection_color,
160 );
161 }
162 c_x += c_w;
163 }
164 }
165
166 if run.glyphs.is_empty() && end.line > line_i {
167 range_opt = Some((0, buffer.size().0.unwrap_or(0.0) as i32));
169 }
170
171 if let Some((mut min, mut max)) = range_opt.take() {
172 if end.line > line_i {
173 if run.rtl {
175 min = 0;
176 } else {
177 max = buffer.size().0.unwrap_or(0.0) as i32;
178 }
179 }
180 f(
181 min,
182 line_top as i32,
183 cmp::max(0, max - min) as u32,
184 line_height as u32,
185 selection_color,
186 );
187 }
188 }
189 }
190
191 if let Some((x, y)) = cursor_position(&self.cursor, &run) {
193 f(x, y, 1, line_height as u32, cursor_color);
194 }
195
196 for glyph in run.glyphs {
197 let physical_glyph = glyph.physical((0., 0.), 1.0);
198
199 let mut glyph_color = glyph.color_opt.map_or(text_color, |some| some);
200 if text_color != selected_text_color {
201 if let Some((start, end)) = selection_bounds {
202 if line_i >= start.line
203 && line_i <= end.line
204 && (start.line != line_i || glyph.end > start.index)
205 && (end.line != line_i || glyph.start < end.index)
206 {
207 glyph_color = selected_text_color;
208 }
209 }
210 }
211
212 cache.with_pixels(
213 font_system,
214 physical_glyph.cache_key,
215 glyph_color,
216 |x, y, color| {
217 f(
218 physical_glyph.x + x,
219 line_y as i32 + physical_glyph.y + y,
220 1,
221 1,
222 color,
223 );
224 },
225 );
226 }
227 }
228 });
229 }
230}
231
232impl<'buffer> Edit<'buffer> for Editor<'buffer> {
233 fn buffer_ref(&self) -> &BufferRef<'buffer> {
234 &self.buffer_ref
235 }
236
237 fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> {
238 &mut self.buffer_ref
239 }
240
241 fn cursor(&self) -> Cursor {
242 self.cursor
243 }
244
245 fn set_cursor(&mut self, cursor: Cursor) {
246 if self.cursor != cursor {
247 self.cursor = cursor;
248 self.cursor_moved = true;
249 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
250 }
251 }
252
253 fn selection(&self) -> Selection {
254 self.selection
255 }
256
257 fn set_selection(&mut self, selection: Selection) {
258 if self.selection != selection {
259 self.selection = selection;
260 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
261 }
262 }
263
264 fn auto_indent(&self) -> bool {
265 self.auto_indent
266 }
267
268 fn set_auto_indent(&mut self, auto_indent: bool) {
269 self.auto_indent = auto_indent;
270 }
271
272 fn tab_width(&self) -> u16 {
273 self.with_buffer(super::super::buffer::Buffer::tab_width)
274 }
275
276 fn set_tab_width(&mut self, font_system: &mut FontSystem, tab_width: u16) {
277 self.with_buffer_mut(|buffer| buffer.set_tab_width(font_system, tab_width));
278 }
279
280 fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
281 if self.cursor_moved {
282 let cursor = self.cursor;
283 self.with_buffer_mut(|buffer| buffer.shape_until_cursor(font_system, cursor, prune));
284 self.cursor_moved = false;
285 } else {
286 self.with_buffer_mut(|buffer| buffer.shape_until_scroll(font_system, prune));
287 }
288 }
289
290 fn delete_range(&mut self, start: Cursor, end: Cursor) {
291 let change_item = self.with_buffer_mut(|buffer| {
292 let mut change_lines = Vec::new();
294
295 let end_line_opt = if end.line > start.line {
297 let after = buffer.lines[end.line].split_off(end.index);
299
300 let removed = buffer.lines.remove(end.line);
302 change_lines.insert(0, removed);
303
304 Some(after)
305 } else {
306 None
307 };
308
309 for line_i in (start.line + 1..end.line).rev() {
311 let removed = buffer.lines.remove(line_i);
312 change_lines.insert(0, removed);
313 }
314
315 {
317 let line = &mut buffer.lines[start.line];
318
319 let after_opt = if start.line == end.line {
321 Some(line.split_off(end.index))
322 } else {
323 None
324 };
325
326 let removed = line.split_off(start.index);
328 change_lines.insert(0, removed);
329
330 if let Some(after) = after_opt {
332 line.append(&after);
333 }
334
335 if let Some(mut end_line) = end_line_opt {
337 if end_line.ending() == LineEnding::None {
339 end_line.set_ending(line.ending());
340 }
341 line.append(&end_line);
342 }
343 }
344
345 let mut text = String::new();
346 let mut last_ending: Option<LineEnding> = None;
347 for line in change_lines {
348 if let Some(ending) = last_ending {
349 text.push_str(ending.as_str());
350 }
351 text.push_str(line.text());
352 last_ending = Some(line.ending());
353 }
354
355 ChangeItem {
356 start,
357 end,
358 text,
359 insert: false,
360 }
361 });
362
363 if let Some(ref mut change) = self.change {
364 change.items.push(change_item);
365 }
366 }
367
368 fn insert_at(
369 &mut self,
370 mut cursor: Cursor,
371 data: &str,
372 attrs_list: Option<AttrsList>,
373 ) -> Cursor {
374 let mut remaining_split_len = data.len();
375 if remaining_split_len == 0 {
376 return cursor;
377 }
378
379 let change_item = self.with_buffer_mut(|buffer| {
380 let start = cursor;
382
383 while cursor.line >= buffer.lines.len() {
385 let mut last_ending = LineEnding::None;
387 if let Some(last_line) = buffer.lines.last_mut() {
388 last_ending = last_line.ending();
389 if last_ending == LineEnding::None {
391 last_line.set_ending(LineEnding::default());
392 }
393 }
394 let line = BufferLine::new(
395 String::new(),
396 last_ending,
397 AttrsList::new(&attrs_list.as_ref().map_or_else(
398 || {
399 buffer
400 .lines
401 .last()
402 .map_or_else(Attrs::new, |line| line.attrs_list().defaults())
403 },
404 |x| x.defaults(),
405 )),
406 Shaping::Advanced,
407 );
408 buffer.lines.push(line);
409 }
410
411 let line: &mut BufferLine = &mut buffer.lines[cursor.line];
412 let insert_line = cursor.line + 1;
413
414 let after: BufferLine = line.split_off(cursor.index);
416 let after_len = after.text().len();
417
418 let mut final_attrs = attrs_list.unwrap_or_else(|| {
420 AttrsList::new(&line.attrs_list().get_span(cursor.index.saturating_sub(1)))
421 });
422
423 let mut lines: Vec<_> = LineIter::new(data).collect();
425 if lines.last().map(|line| line.1).unwrap_or(LineEnding::None) != LineEnding::None {
427 lines.push((Default::default(), LineEnding::None));
428 }
429 let mut lines_iter = lines.into_iter();
430
431 if let Some((range, ending)) = lines_iter.next() {
433 let data_line = &data[range];
434 let mut these_attrs = final_attrs.split_off(data_line.len());
435 remaining_split_len -= data_line.len() + ending.as_str().len();
436 core::mem::swap(&mut these_attrs, &mut final_attrs);
437 line.append(&BufferLine::new(
438 data_line,
439 ending,
440 these_attrs,
441 Shaping::Advanced,
442 ));
443 }
444 if let Some((range, ending)) = lines_iter.next_back() {
446 let data_line = &data[range];
447 remaining_split_len -= data_line.len() + ending.as_str().len();
448 let mut tmp = BufferLine::new(
449 data_line,
450 ending,
451 final_attrs.split_off(remaining_split_len),
452 Shaping::Advanced,
453 );
454 tmp.append(&after);
455 buffer.lines.insert(insert_line, tmp);
456 cursor.line += 1;
457 } else {
458 line.append(&after);
459 }
460 for (range, ending) in lines_iter.rev() {
462 let data_line = &data[range];
463 remaining_split_len -= data_line.len() + ending.as_str().len();
464 let tmp = BufferLine::new(
465 data_line,
466 ending,
467 final_attrs.split_off(remaining_split_len),
468 Shaping::Advanced,
469 );
470 buffer.lines.insert(insert_line, tmp);
471 cursor.line += 1;
472 }
473
474 assert_eq!(remaining_split_len, 0);
475
476 cursor.index = buffer.lines[cursor.line].text().len() - after_len;
478
479 ChangeItem {
480 start,
481 end: cursor,
482 text: data.to_string(),
483 insert: true,
484 }
485 });
486
487 if let Some(ref mut change) = self.change {
488 change.items.push(change_item);
489 }
490
491 cursor
492 }
493
494 fn copy_selection(&self) -> Option<String> {
495 let (start, end) = self.selection_bounds()?;
496 self.with_buffer(|buffer| {
497 let mut selection = String::new();
498 {
500 if start.line == end.line {
502 selection.push_str(&buffer.lines[start.line].text()[start.index..end.index]);
503 } else {
504 selection.push_str(&buffer.lines[start.line].text()[start.index..]);
505 selection.push('\n');
506 }
507 }
508
509 for line_i in start.line + 1..end.line {
511 selection.push_str(buffer.lines[line_i].text());
512 selection.push('\n');
513 }
514
515 if end.line > start.line {
517 selection.push_str(&buffer.lines[end.line].text()[..end.index]);
519 }
520
521 Some(selection)
522 })
523 }
524
525 fn delete_selection(&mut self) -> bool {
526 let Some((start, end)) = self.selection_bounds() else {
527 return false;
528 };
529
530 self.cursor = start;
532
533 self.selection = Selection::None;
535
536 self.delete_range(start, end);
538
539 true
540 }
541
542 fn apply_change(&mut self, change: &Change) -> bool {
543 if let Some(pending) = self.change.take() {
545 if !pending.items.is_empty() {
546 log::warn!("pending change caused apply_change to be ignored!");
548 self.change = Some(pending);
549 return false;
550 }
551 }
552
553 for item in &change.items {
554 if item.insert {
556 self.cursor = self.insert_at(item.start, &item.text, None);
557 } else {
558 self.cursor = item.start;
559 self.delete_range(item.start, item.end);
560 }
561 }
562 true
563 }
564
565 fn start_change(&mut self) {
566 if self.change.is_none() {
567 self.change = Some(Change::default());
568 }
569 }
570
571 fn finish_change(&mut self) -> Option<Change> {
572 self.change.take()
573 }
574
575 fn action(&mut self, font_system: &mut FontSystem, action: Action) {
576 let old_cursor = self.cursor;
577
578 match action {
579 Action::Motion(motion) => {
580 let cursor = self.cursor;
581 let cursor_x_opt = self.cursor_x_opt;
582 if let Some((new_cursor, new_cursor_x_opt)) = self.with_buffer_mut(|buffer| {
583 buffer.cursor_motion(font_system, cursor, cursor_x_opt, motion)
584 }) {
585 self.cursor = new_cursor;
586 self.cursor_x_opt = new_cursor_x_opt;
587 }
588 }
589 Action::Escape => {
590 match self.selection {
591 Selection::None => {}
592 _ => self.with_buffer_mut(|buffer| buffer.set_redraw(true)),
593 }
594 self.selection = Selection::None;
595 }
596 Action::Insert(character) => {
597 if character.is_control() && !['\t', '\n', '\u{92}'].contains(&character) {
598 log::debug!("Refusing to insert control character {character:?}");
600 } else if character == '\n' {
601 self.action(font_system, Action::Enter);
602 } else {
603 let mut str_buf = [0u8; 8];
604 let str_ref = character.encode_utf8(&mut str_buf);
605 self.insert_string(str_ref, None);
606 }
607 }
608 Action::Enter => {
609 if self.auto_indent {
611 let mut string = String::from("\n");
612 self.with_buffer(|buffer| {
613 let line = &buffer.lines[self.cursor.line];
614 let text = line.text();
615 for c in text.chars() {
616 if c.is_whitespace() {
617 string.push(c);
618 } else {
619 break;
620 }
621 }
622 });
623 self.insert_string(&string, None);
624 } else {
625 self.insert_string("\n", None);
626 }
627
628 let line_i = self.cursor.line;
630 self.with_buffer_mut(|buffer| {
631 buffer.line_layout(font_system, line_i);
632 });
633 }
634 Action::Backspace => {
635 if self.delete_selection() {
636 } else {
638 let end = self.cursor;
640
641 if self.cursor.index > 0 {
642 self.cursor.index = self.with_buffer(|buffer| {
644 buffer.lines[self.cursor.line].text()[..self.cursor.index]
645 .char_indices()
646 .next_back()
647 .map_or(0, |(i, _)| i)
648 });
649 } else if self.cursor.line > 0 {
650 self.cursor.line -= 1;
652 self.cursor.index =
653 self.with_buffer(|buffer| buffer.lines[self.cursor.line].text().len());
654 }
655
656 if self.cursor != end {
657 self.delete_range(self.cursor, end);
659 }
660 }
661 }
662 Action::Delete => {
663 if self.delete_selection() {
664 } else {
666 let mut start = self.cursor;
668 let mut end = self.cursor;
669
670 self.with_buffer(|buffer| {
671 if start.index < buffer.lines[start.line].text().len() {
672 let line = &buffer.lines[start.line];
673
674 let range_opt = line
675 .text()
676 .grapheme_indices(true)
677 .take_while(|(i, _)| *i <= start.index)
678 .last()
679 .map(|(i, c)| i..(i + c.len()));
680
681 if let Some(range) = range_opt {
682 start.index = range.start;
683 end.index = range.end;
684 }
685 } else if start.line + 1 < buffer.lines.len() {
686 end.line += 1;
687 end.index = 0;
688 }
689 });
690
691 if start != end {
692 self.cursor = start;
693 self.delete_range(start, end);
694 }
695 }
696 }
697 Action::Indent => {
698 let (start, end) = match self.selection_bounds() {
700 Some(some) => some,
701 None => (self.cursor, self.cursor),
702 };
703
704 let tab_width: usize = self.tab_width().into();
706 for line_i in start.line..=end.line {
707 let mut after_whitespace = 0;
709 let mut required_indent = 0;
710 self.with_buffer(|buffer| {
711 let line = &buffer.lines[line_i];
712 let text = line.text();
713
714 if self.selection == Selection::None {
715 let whitespace_length = match line.text()[0..self.cursor.index]
717 .chars()
718 .rev()
719 .position(|c| !c.is_whitespace())
720 {
721 Some(length) => length,
722 None => self.cursor.index,
724 };
725 required_indent = tab_width - (whitespace_length % tab_width);
726 after_whitespace = self.cursor.index;
727 } else {
728 for (count, (index, c)) in text.char_indices().enumerate() {
730 if !c.is_whitespace() {
731 after_whitespace = index;
732 required_indent = tab_width - (count % tab_width);
733 break;
734 }
735 }
736 }
737 });
738
739 self.insert_at(
740 Cursor::new(line_i, after_whitespace),
741 &" ".repeat(required_indent),
742 None,
743 );
744
745 if self.cursor.line == line_i {
747 if self.cursor.index < after_whitespace {
749 self.cursor.index = after_whitespace;
750 }
751 self.cursor.index += required_indent;
752 }
753
754 match self.selection {
756 Selection::None => {}
757 Selection::Normal(ref mut select)
758 | Selection::Line(ref mut select)
759 | Selection::Word(ref mut select) => {
760 if select.line == line_i && select.index >= after_whitespace {
761 select.index += required_indent;
762 }
763 }
764 }
765 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
767 }
768 }
769 Action::Unindent => {
770 let (start, end) = match self.selection_bounds() {
772 Some(some) => some,
773 None => (self.cursor, self.cursor),
774 };
775
776 let tab_width: usize = self.tab_width().into();
778 for line_i in start.line..=end.line {
779 let mut last_indent = 0;
781 let mut after_whitespace = 0;
782 self.with_buffer(|buffer| {
783 let line = &buffer.lines[line_i];
784 let text = line.text();
785 after_whitespace = text.len();
787 for (count, (index, c)) in text.char_indices().enumerate() {
788 if !c.is_whitespace() {
789 after_whitespace = index;
790 break;
791 }
792 if count % tab_width == 0 {
793 last_indent = index;
794 }
795 }
796 });
797
798 if last_indent == after_whitespace {
800 continue;
801 }
802
803 self.delete_range(
805 Cursor::new(line_i, last_indent),
806 Cursor::new(line_i, after_whitespace),
807 );
808
809 if self.cursor.line == line_i && self.cursor.index > last_indent {
811 self.cursor.index -= after_whitespace - last_indent;
812 }
813
814 match self.selection {
816 Selection::None => {}
817 Selection::Normal(ref mut select)
818 | Selection::Line(ref mut select)
819 | Selection::Word(ref mut select) => {
820 if select.line == line_i && select.index > last_indent {
821 select.index -= after_whitespace - last_indent;
822 }
823 }
824 }
825
826 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
828 }
829 }
830 Action::Click { x, y } => {
831 self.set_selection(Selection::None);
832
833 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
834 {
835 if new_cursor != self.cursor {
836 self.cursor = new_cursor;
837 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
838 }
839 }
840 }
841 Action::DoubleClick { x, y } => {
842 self.set_selection(Selection::None);
843
844 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
845 {
846 if new_cursor != self.cursor {
847 self.cursor = new_cursor;
848 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
849 }
850 self.selection = Selection::Word(self.cursor);
851 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
852 }
853 }
854 Action::TripleClick { x, y } => {
855 self.set_selection(Selection::None);
856
857 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
858 {
859 if new_cursor != self.cursor {
860 self.cursor = new_cursor;
861 }
862 self.selection = Selection::Line(self.cursor);
863 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
864 }
865 }
866 Action::Drag { x, y } => {
867 if self.selection == Selection::None {
868 self.selection = Selection::Normal(self.cursor);
869 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
870 }
871
872 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
873 {
874 if new_cursor != self.cursor {
875 self.cursor = new_cursor;
876 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
877 }
878 }
879 }
880 Action::Scroll { pixels } => {
881 self.with_buffer_mut(|buffer| {
882 let mut scroll = buffer.scroll();
883 scroll.vertical += pixels;
885 buffer.set_scroll(scroll);
886 });
887 }
888 }
889
890 if old_cursor != self.cursor {
891 self.cursor_moved = true;
892 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
893
894 }
910 }
911
912 fn cursor_position(&self) -> Option<(i32, i32)> {
913 self.with_buffer(|buffer| {
914 buffer
915 .layout_runs()
916 .find_map(|run| cursor_position(&self.cursor, &run))
917 })
918 }
919}
920
921impl BorrowedWithFontSystem<'_, Editor<'_>> {
922 #[cfg(feature = "swash")]
923 pub fn draw<F>(
924 &mut self,
925 cache: &mut crate::SwashCache,
926 text_color: Color,
927 cursor_color: Color,
928 selection_color: Color,
929 selected_text_color: Color,
930 f: F,
931 ) where
932 F: FnMut(i32, i32, u32, u32, Color),
933 {
934 self.inner.draw(
935 self.font_system,
936 cache,
937 text_color,
938 cursor_color,
939 selection_color,
940 selected_text_color,
941 f,
942 );
943 }
944}