From 6528e9f804b76bc60bd1305f86b8b7388753a8b7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 14 Dec 2023 10:38:58 -0700 Subject: [PATCH] multiview example --- examples/multiview/Cargo.toml | 17 ++++ examples/multiview/src/main.rs | 177 +++++++++++++++++++++++++++++++++ multiview.sh | 3 + 3 files changed, 197 insertions(+) create mode 100644 examples/multiview/Cargo.toml create mode 100644 examples/multiview/src/main.rs create mode 100755 multiview.sh diff --git a/examples/multiview/Cargo.toml b/examples/multiview/Cargo.toml new file mode 100644 index 0000000..8afde53 --- /dev/null +++ b/examples/multiview/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "multiview" +version = "0.1.0" +authors = ["Jeremy Soller "] +edition = "2021" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +cosmic-text = { path = "../.." } +env_logger = "0.10" +fontdb = "0.13" +log = "0.4" +softbuffer = "0.4" +tiny-skia = "0.11" +unicode-segmentation = "1.7" +winit = "0.29" diff --git a/examples/multiview/src/main.rs b/examples/multiview/src/main.rs new file mode 100644 index 0000000..9348bed --- /dev/null +++ b/examples/multiview/src/main.rs @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use cosmic_text::{Action, Attrs, Buffer, Edit, Family, FontSystem, Metrics, Shaping, SwashCache}; +use std::{collections::HashMap, env, fs, num::NonZeroU32, rc::Rc, slice}; +use tiny_skia::{Color, Paint, PixmapMut, Rect, Transform}; +use winit::{ + event::{ElementState, Event, KeyEvent, WindowEvent}, + event_loop::{ControlFlow, EventLoop}, + keyboard::{Key, NamedKey}, + window::{Window as WinitWindow, WindowBuilder}, +}; + +fn main() { + env_logger::init(); + + let path = if let Some(arg) = env::args().nth(1) { + arg + } else { + "sample/hello.txt".to_string() + }; + + let mut font_system = FontSystem::new(); + + let mut swash_cache = SwashCache::new(); + + let mut buffer = Buffer::new_empty(Metrics::new(14.0, 20.0)); + + let mut buffer = buffer.borrow_with(&mut font_system); + + let attrs = Attrs::new().family(Family::Monospace); + match fs::read_to_string(&path) { + Ok(text) => buffer.set_text(&text, attrs, Shaping::Advanced), + Err(err) => { + log::error!("failed to load {:?}: {}", path, err); + } + } + + let event_loop = EventLoop::new().unwrap(); + + struct Window { + window: Rc, + context: softbuffer::Context>, + surface: softbuffer::Surface, Rc>, + scroll: i32, + } + let mut windows = HashMap::new(); + for _ in 0..2 { + let window = Rc::new(WindowBuilder::new().build(&event_loop).unwrap()); + let context = softbuffer::Context::new(window.clone()).unwrap(); + let surface = softbuffer::Surface::new(&context, window.clone()).unwrap(); + windows.insert( + window.id(), + Window { + window, + context, + surface, + scroll: 0, + }, + ); + } + + event_loop + .run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Wait); + + match event { + Event::WindowEvent { + window_id, + event: WindowEvent::RedrawRequested, + } => { + if let Some(Window { + window, + surface, + scroll, + .. + }) = windows.get_mut(&window_id) + { + let (width, height) = { + let size = window.inner_size(); + (size.width, size.height) + }; + surface + .resize( + NonZeroU32::new(width).unwrap(), + NonZeroU32::new(height).unwrap(), + ) + .unwrap(); + + let mut surface_buffer = surface.buffer_mut().unwrap(); + let surface_buffer_u8 = unsafe { + slice::from_raw_parts_mut( + surface_buffer.as_mut_ptr() as *mut u8, + surface_buffer.len() * 4, + ) + }; + let mut pixmap = + PixmapMut::from_bytes(surface_buffer_u8, width, height).unwrap(); + pixmap.fill(Color::from_rgba8(0, 0, 0, 0xFF)); + + // Set scroll to view scroll + buffer.set_scroll(*scroll); + // Set size, will relayout and shape until scroll if changed + buffer.set_size(width as f32, height as f32); + // Shape until scroll, ensures scroll is clamped + buffer.shape_until_scroll(); + // Update scroll after buffer clamps it + *scroll = buffer.scroll(); + + let mut paint = Paint::default(); + paint.anti_alias = false; + let transform = Transform::identity(); + buffer.draw( + &mut swash_cache, + cosmic_text::Color::rgb(0xFF, 0xFF, 0xFF), + |x, y, w, h, color| { + paint.set_color_rgba8(color.r(), color.g(), color.b(), color.a()); + pixmap.fill_rect( + Rect::from_xywh(x as f32, y as f32, w as f32, h as f32) + .unwrap(), + &paint, + transform, + None, + ); + }, + ); + + surface_buffer.present().unwrap(); + } + } + Event::WindowEvent { + event: + WindowEvent::KeyboardInput { + event: + KeyEvent { + logical_key, + text, + state, + .. + }, + .. + }, + window_id, + } => { + if let Some(Window { window, scroll, .. }) = windows.get_mut(&window_id) { + if state == ElementState::Pressed { + match logical_key { + Key::Named(NamedKey::ArrowDown) => { + *scroll += 1; + } + Key::Named(NamedKey::ArrowUp) => { + *scroll -= 1; + } + Key::Named(NamedKey::PageDown) => { + *scroll += buffer.visible_lines(); + } + Key::Named(NamedKey::PageUp) => { + *scroll -= buffer.visible_lines(); + } + _ => {} + } + } + println!("{:?} {:?} {:?}", logical_key, text, state); + window.request_redraw(); + } + } + Event::WindowEvent { + event: WindowEvent::CloseRequested, + window_id: _, + } => { + //TODO: just close one window + elwt.exit(); + } + _ => {} + } + }) + .unwrap(); +} diff --git a/multiview.sh b/multiview.sh new file mode 100755 index 0000000..9574abc --- /dev/null +++ b/multiview.sh @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT OR Apache-2.0 + +RUST_LOG="cosmic_text=debug,multiview=debug" cargo run --release --package multiview -- "$@"