Optimize drawing and draw cursor
This commit is contained in:
parent
dd823c182d
commit
09a153bc8e
1 changed files with 110 additions and 37 deletions
147
src/main.rs
147
src/main.rs
|
|
@ -14,10 +14,10 @@ use alacritty_terminal::{
|
||||||
};
|
};
|
||||||
use cosmic_text::{
|
use cosmic_text::{
|
||||||
Attrs, AttrsList, Buffer, BufferLine, Family, FontSystem, Metrics, Shaping, Style, SwashCache,
|
Attrs, AttrsList, Buffer, BufferLine, Family, FontSystem, Metrics, Shaping, Style, SwashCache,
|
||||||
Weight, Wrap,
|
SwashContent, Weight, Wrap,
|
||||||
};
|
};
|
||||||
use std::{num::NonZeroU32, rc::Rc, slice, sync::Arc};
|
use std::{mem, num::NonZeroU32, rc::Rc, slice, sync::Arc, time::Instant};
|
||||||
use tiny_skia::{Paint, PixmapMut, Rect, Transform};
|
use tiny_skia::{ColorU8, Paint, PixmapMut, PixmapPaint, PixmapRef, Rect, Transform};
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{ElementState, Event as WinitEvent, KeyEvent, Modifiers, WindowEvent},
|
event::{ElementState, Event as WinitEvent, KeyEvent, Modifiers, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy},
|
event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy},
|
||||||
|
|
@ -192,6 +192,8 @@ fn main() {
|
||||||
window_id,
|
window_id,
|
||||||
event: WindowEvent::RedrawRequested,
|
event: WindowEvent::RedrawRequested,
|
||||||
} if window_id == window.id() => {
|
} if window_id == window.id() => {
|
||||||
|
let instant = Instant::now();
|
||||||
|
|
||||||
let (width, height) = {
|
let (width, height) = {
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
(size.width, size.height)
|
(size.width, size.height)
|
||||||
|
|
@ -225,17 +227,8 @@ fn main() {
|
||||||
|
|
||||||
let mut paint = Paint::default();
|
let mut paint = Paint::default();
|
||||||
paint.anti_alias = false;
|
paint.anti_alias = false;
|
||||||
|
let pixmap_paint = PixmapPaint::default();
|
||||||
let transform = Transform::identity();
|
let transform = Transform::identity();
|
||||||
let mut f = |x: f32, y: f32, w: f32, h: f32, color: cosmic_text::Color| {
|
|
||||||
// Have to swap RGB for BGR
|
|
||||||
paint.set_color_rgba8(color.b(), color.g(), color.r(), color.a());
|
|
||||||
pixmap.fill_rect(
|
|
||||||
Rect::from_xywh(x, y, w, h).unwrap(),
|
|
||||||
&paint,
|
|
||||||
transform,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
for run in buffer.layout_runs() {
|
for run in buffer.layout_runs() {
|
||||||
for glyph in run.glyphs.iter() {
|
for glyph in run.glyphs.iter() {
|
||||||
let physical_glyph = glyph.physical((0., 0.), 1.0);
|
let physical_glyph = glyph.physical((0., 0.), 1.0);
|
||||||
|
|
@ -246,34 +239,101 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let background_color = cosmic_text::Color(glyph.metadata as u32);
|
let background_color = cosmic_text::Color(glyph.metadata as u32);
|
||||||
|
if background_color.0 != 0xFF000000 {
|
||||||
|
//TODO: Have to swap RGB for BGR
|
||||||
|
paint.set_color_rgba8(
|
||||||
|
background_color.b(),
|
||||||
|
background_color.g(),
|
||||||
|
background_color.r(),
|
||||||
|
background_color.a(),
|
||||||
|
);
|
||||||
|
pixmap.fill_rect(
|
||||||
|
Rect::from_xywh(
|
||||||
|
glyph.x,
|
||||||
|
run.line_top,
|
||||||
|
glyph.w,
|
||||||
|
metrics.line_height,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
&paint,
|
||||||
|
transform,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
f(
|
match swash_cache.get_image(&mut font_system, physical_glyph.cache_key)
|
||||||
glyph.x,
|
{
|
||||||
run.line_top,
|
Some(image) if !image.data.is_empty() => {
|
||||||
glyph.w,
|
let mut data = Vec::with_capacity(
|
||||||
metrics.line_height,
|
(image.placement.width * image.placement.height) as usize,
|
||||||
background_color,
|
|
||||||
);
|
|
||||||
|
|
||||||
swash_cache.with_pixels(
|
|
||||||
&mut font_system,
|
|
||||||
physical_glyph.cache_key,
|
|
||||||
glyph_color,
|
|
||||||
|x, y, color| {
|
|
||||||
f(
|
|
||||||
(physical_glyph.x + x) as f32,
|
|
||||||
run.line_y + (physical_glyph.y + y) as f32,
|
|
||||||
1.0,
|
|
||||||
1.0,
|
|
||||||
color,
|
|
||||||
);
|
);
|
||||||
},
|
match image.content {
|
||||||
);
|
SwashContent::Mask => {
|
||||||
|
let mut i = 0;
|
||||||
|
while i < image.data.len() {
|
||||||
|
//TODO: Have to swap RGB for BGR
|
||||||
|
data.push(
|
||||||
|
ColorU8::from_rgba(
|
||||||
|
glyph_color.b(),
|
||||||
|
glyph_color.g(),
|
||||||
|
glyph_color.r(),
|
||||||
|
image.data[i],
|
||||||
|
)
|
||||||
|
.premultiply(),
|
||||||
|
);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SwashContent::Color => {
|
||||||
|
let mut i = 0;
|
||||||
|
while i < image.data.len() {
|
||||||
|
//TODO: Have to swap RGB for BGR
|
||||||
|
data.push(
|
||||||
|
ColorU8::from_rgba(
|
||||||
|
image.data[i + 2],
|
||||||
|
image.data[i + 1],
|
||||||
|
image.data[i],
|
||||||
|
image.data[i + 3],
|
||||||
|
)
|
||||||
|
.premultiply(),
|
||||||
|
);
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SwashContent::SubpixelMask => {
|
||||||
|
todo!("TODO: SubpixelMask");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let glyph_pixmap = PixmapRef::from_bytes(
|
||||||
|
unsafe {
|
||||||
|
slice::from_raw_parts(
|
||||||
|
data.as_ptr() as *const u8,
|
||||||
|
data.len() * 4,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
image.placement.width,
|
||||||
|
image.placement.height,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
pixmap.draw_pixmap(
|
||||||
|
physical_glyph.x + image.placement.left,
|
||||||
|
run.line_y as i32 + physical_glyph.y - image.placement.top,
|
||||||
|
glyph_pixmap,
|
||||||
|
&pixmap_paint,
|
||||||
|
transform,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.set_redraw(false);
|
buffer.set_redraw(false);
|
||||||
|
|
||||||
surface_buffer.present().unwrap();
|
surface_buffer.present().unwrap();
|
||||||
|
|
||||||
|
println!("draw {:?}", instant.elapsed());
|
||||||
}
|
}
|
||||||
WinitEvent::WindowEvent {
|
WinitEvent::WindowEvent {
|
||||||
event:
|
event:
|
||||||
|
|
@ -329,6 +389,7 @@ fn main() {
|
||||||
dimensions.height = physical_size.height as f32;
|
dimensions.height = physical_size.height as f32;
|
||||||
notifier.on_resize(dimensions.into());
|
notifier.on_resize(dimensions.into());
|
||||||
term.lock().resize(dimensions);
|
term.lock().resize(dimensions);
|
||||||
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
WinitEvent::WindowEvent {
|
WinitEvent::WindowEvent {
|
||||||
event: WindowEvent::CloseRequested,
|
event: WindowEvent::CloseRequested,
|
||||||
|
|
@ -344,13 +405,17 @@ fn main() {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let instant = Instant::now();
|
||||||
|
|
||||||
//TODO: is redraw needed after all events?
|
//TODO: is redraw needed after all events?
|
||||||
//TODO: use LineDamageBounds
|
//TODO: use LineDamageBounds
|
||||||
{
|
{
|
||||||
let mut last_point = Point::new(Line(0), Column(0));
|
let mut last_point = Point::new(Line(0), Column(0));
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
let mut attrs_list = AttrsList::new(default_attrs);
|
let mut attrs_list = AttrsList::new(default_attrs);
|
||||||
for indexed in term.lock().grid().display_iter() {
|
let term_guard = term.lock();
|
||||||
|
let grid = term_guard.grid();
|
||||||
|
for indexed in grid.display_iter() {
|
||||||
if indexed.point.line != last_point.line {
|
if indexed.point.line != last_point.line {
|
||||||
let line_i = last_point.line.0 as usize;
|
let line_i = last_point.line.0 as usize;
|
||||||
while line_i >= buffer.lines.len() {
|
while line_i >= buffer.lines.len() {
|
||||||
|
|
@ -397,9 +462,15 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut attrs = default_attrs;
|
let mut attrs = default_attrs;
|
||||||
attrs = attrs.color(convert_color(indexed.cell.fg));
|
let mut fg = convert_color(indexed.cell.fg);
|
||||||
|
let mut bg = convert_color(indexed.cell.bg);
|
||||||
|
//TODO: better handling of cursor
|
||||||
|
if indexed.point == grid.cursor.point {
|
||||||
|
mem::swap(&mut fg, &mut bg);
|
||||||
|
}
|
||||||
|
attrs = attrs.color(fg);
|
||||||
// Use metadata as background color
|
// Use metadata as background color
|
||||||
attrs = attrs.metadata(convert_color(indexed.cell.bg).0 as usize);
|
attrs = attrs.metadata(bg.0 as usize);
|
||||||
//TODO: more flags
|
//TODO: more flags
|
||||||
if indexed.cell.flags.contains(Flags::BOLD) {
|
if indexed.cell.flags.contains(Flags::BOLD) {
|
||||||
attrs = attrs.weight(Weight::BOLD);
|
attrs = attrs.weight(Weight::BOLD);
|
||||||
|
|
@ -433,6 +504,8 @@ fn main() {
|
||||||
if buffer.redraw() {
|
if buffer.redraw() {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("buffer update {:?}", instant.elapsed());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue