Improve performance of text_box renderer
This commit is contained in:
parent
e2f6e6d879
commit
bacb9e6848
2 changed files with 92 additions and 59 deletions
26
src/main.rs
26
src/main.rs
|
|
@ -1,20 +1,16 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
app::{self, Command, Core, Settings},
|
app::{Command, Core, Settings},
|
||||||
executor,
|
executor,
|
||||||
iced::{
|
iced::{
|
||||||
self,
|
widget::{column, row, text},
|
||||||
widget::{column, container, horizontal_space, pick_list, row, text},
|
Alignment, Length,
|
||||||
Alignment, Color, Length,
|
|
||||||
},
|
},
|
||||||
theme::{self, Theme, ThemeType},
|
widget::{icon, segmented_button, view_switcher},
|
||||||
widget::{button, icon, segmented_button, toggler, view_switcher},
|
|
||||||
ApplicationExt, Element,
|
ApplicationExt, Element,
|
||||||
};
|
};
|
||||||
use cosmic_text::{
|
use cosmic_text::{Attrs, Buffer, Edit, FontSystem, Metrics, SyntaxEditor, SyntaxSystem};
|
||||||
Attrs, AttrsList, Buffer, Edit, FontSystem, Metrics, SyntaxEditor, SyntaxSystem, Wrap,
|
|
||||||
};
|
|
||||||
use std::{env, fs, path::PathBuf, sync::Mutex};
|
use std::{env, fs, path::PathBuf, sync::Mutex};
|
||||||
|
|
||||||
use self::menu_list::MenuList;
|
use self::menu_list::MenuList;
|
||||||
|
|
@ -204,14 +200,20 @@ impl cosmic::Application for App {
|
||||||
|
|
||||||
/// Creates the application, and optionally emits command on initialize.
|
/// Creates the application, and optionally emits command on initialize.
|
||||||
fn init(core: Core, _flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
fn init(core: Core, _flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||||
let mut tab_model = segmented_button::Model::builder().build();
|
let mut app = App {
|
||||||
|
core,
|
||||||
let mut app = App { core, tab_model };
|
tab_model: segmented_button::Model::builder().build(),
|
||||||
|
};
|
||||||
|
|
||||||
for path in env::args().skip(1) {
|
for path in env::args().skip(1) {
|
||||||
app.open_tab(Some(PathBuf::from(path)));
|
app.open_tab(Some(PathBuf::from(path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open an empty file if no arguments provided
|
||||||
|
if app.tab_model.iter().next().is_none() {
|
||||||
|
app.open_tab(None);
|
||||||
|
}
|
||||||
|
|
||||||
let command = app.update_title();
|
let command = app.update_title();
|
||||||
(app, command)
|
(app, command)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
125
src/text_box.rs
125
src/text_box.rs
|
|
@ -74,20 +74,7 @@ pub fn text_box<'a, Editor>(editor: &'a Mutex<Editor>) -> TextBox<'a, Editor> {
|
||||||
TextBox::new(editor)
|
TextBox::new(editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_pixel(
|
fn draw_pixel(buffer: &mut [u32], width: i32, height: i32, x: i32, y: i32, color: u32) {
|
||||||
buffer: &mut [u8],
|
|
||||||
width: i32,
|
|
||||||
height: i32,
|
|
||||||
x: i32,
|
|
||||||
y: i32,
|
|
||||||
color: cosmic_text::Color,
|
|
||||||
) {
|
|
||||||
let alpha = (color.0 >> 24) & 0xFF;
|
|
||||||
if alpha == 0 {
|
|
||||||
// Do not draw if alpha is zero
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if y < 0 || y >= height {
|
if y < 0 || y >= height {
|
||||||
// Skip if y out of bounds
|
// Skip if y out of bounds
|
||||||
return;
|
return;
|
||||||
|
|
@ -98,29 +85,72 @@ fn draw_pixel(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = (y as usize * width as usize + x as usize) * 4;
|
let alpha = (color >> 24) & 0xFF;
|
||||||
|
if alpha == 0 {
|
||||||
let mut current = buffer[offset + 2] as u32
|
// Do not draw if alpha is zero
|
||||||
| (buffer[offset + 1] as u32) << 8
|
return;
|
||||||
| (buffer[offset + 0] as u32) << 16
|
|
||||||
| (buffer[offset + 3] as u32) << 24;
|
|
||||||
|
|
||||||
if alpha >= 255 || current == 0 {
|
|
||||||
// Alpha is 100% or current is null, replace with no blending
|
|
||||||
current = color.0;
|
|
||||||
} else {
|
|
||||||
// Alpha blend with current value
|
|
||||||
let n_alpha = 255 - alpha;
|
|
||||||
let rb = ((n_alpha * (current & 0x00FF00FF)) + (alpha * (color.0 & 0x00FF00FF))) >> 8;
|
|
||||||
let ag = (n_alpha * ((current & 0xFF00FF00) >> 8))
|
|
||||||
+ (alpha * (0x01000000 | ((color.0 & 0x0000FF00) >> 8)));
|
|
||||||
current = (rb & 0x00FF00FF) | (ag & 0xFF00FF00);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buffer[offset + 2] = current as u8;
|
//TODO: improve performance
|
||||||
buffer[offset + 1] = (current >> 8) as u8;
|
fn draw_rect(
|
||||||
buffer[offset + 0] = (current >> 16) as u8;
|
buffer: &mut [u32],
|
||||||
buffer[offset + 3] = (current >> 24) as u8;
|
image_w: i32,
|
||||||
|
image_h: i32,
|
||||||
|
start_x: i32,
|
||||||
|
start_y: i32,
|
||||||
|
w: i32,
|
||||||
|
h: i32,
|
||||||
|
color: u32,
|
||||||
|
) {
|
||||||
|
let alpha = (color >> 24) & 0xFF;
|
||||||
|
if alpha == 0 {
|
||||||
|
// Do not draw if alpha is zero
|
||||||
|
return;
|
||||||
|
} else if alpha >= 255 {
|
||||||
|
// Handle overwrite
|
||||||
|
for y in start_y..start_y + h {
|
||||||
|
if y < 0 || y >= image_h {
|
||||||
|
// Skip if y out of bounds
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let line_offset = y as usize * image_w as usize;
|
||||||
|
for x in start_x..start_x + w {
|
||||||
|
if x < 0 || x >= image_w {
|
||||||
|
// Skip if x out of bounds
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset = line_offset + x as usize;
|
||||||
|
buffer[offset] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let n_alpha = 255 - alpha;
|
||||||
|
for y in start_y..start_y + h {
|
||||||
|
if y < 0 || y >= image_h {
|
||||||
|
// Skip if y out of bounds
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let line_offset = y as usize * image_w as usize;
|
||||||
|
for x in start_x..start_x + w {
|
||||||
|
if x < 0 || x >= image_w {
|
||||||
|
// Skip if x out of bounds
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alpha blend with current value
|
||||||
|
let offset = line_offset + x as usize;
|
||||||
|
let current = buffer[offset];
|
||||||
|
let rb = ((n_alpha * (current & 0x00FF00FF)) + (alpha * (color & 0x00FF00FF))) >> 8;
|
||||||
|
let ag = (n_alpha * ((current & 0xFF00FF00) >> 8))
|
||||||
|
+ (alpha * (0x01000000 | ((color & 0x0000FF00) >> 8)));
|
||||||
|
buffer[offset] = (rb & 0x00FF00FF) | (ag & 0xFF00FF00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'editor, Editor, Message, Renderer> Widget<Message, Renderer> for TextBox<'a, Editor>
|
impl<'a, 'editor, Editor, Message, Renderer> Widget<Message, Renderer> for TextBox<'a, Editor>
|
||||||
|
|
@ -250,18 +280,19 @@ where
|
||||||
|
|
||||||
// Draw to pixel buffer
|
// Draw to pixel buffer
|
||||||
let mut pixels = vec![0; image_w as usize * image_h as usize * 4];
|
let mut pixels = vec![0; image_w as usize * image_h as usize * 4];
|
||||||
editor.draw(
|
{
|
||||||
&mut state.cache.lock().unwrap(),
|
let buffer = unsafe {
|
||||||
text_color,
|
std::slice::from_raw_parts_mut(pixels.as_mut_ptr() as *mut u32, pixels.len() / 4)
|
||||||
|x, y, w, h, color| {
|
};
|
||||||
//TODO: improve performance
|
|
||||||
for row in 0..h as i32 {
|
editor.draw(
|
||||||
for col in 0..w as i32 {
|
&mut state.cache.lock().unwrap(),
|
||||||
draw_pixel(&mut pixels, image_w, image_h, x + col, y + row, color);
|
text_color,
|
||||||
}
|
|x, y, w, h, color| {
|
||||||
}
|
draw_rect(buffer, image_w, image_h, x, y, w as i32, h as i32, color.0);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Restore original metrics
|
// Restore original metrics
|
||||||
editor.buffer_mut().set_metrics(metrics);
|
editor.buffer_mut().set_metrics(metrics);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue