ratatui_wgpu/lib.rs
1//! # Getting Started
2//! Check out the [examples](https://github.com/Jesterhearts/ratatui-wgpu/tree/main/examples)
3//! for a number of programs using `winit` for both native and web.
4//!
5//! A [`WgpuBackend`] can be constructed using a [`Builder`] and then provided
6//! to a [`Terminal`](ratatui::Terminal). After that, rendering can be done as
7//! normal using the ratatui library. If you need custom shader post-processing,
8//! see the [`PostProcessor`] trait or the
9//! [`DefaultPostProcessor`](shaders::DefaultPostProcessor) implementation for
10//! guidance.
11//!
12//! Here's a short example using winit on native with the default post processor
13//! implementation:
14//! ```
15//! # use std::{
16//! # num::NonZeroU32,
17//! # sync::Arc,
18//! # };
19//! #
20//! # use chrono::Local;
21//! # use ratatui::{
22//! # prelude::*,
23//! # widgets::*,
24//! # };
25//! # use ratatui_wgpu::{
26//! # Builder,
27//! # Font,
28//! # WgpuBackend,
29//! # Dimensions,
30//! # };
31//! # use winit::{
32//! # application::ApplicationHandler,
33//! # event::WindowEvent,
34//! # event_loop::EventLoop,
35//! # window::{
36//! # Window,
37//! # WindowAttributes,
38//! # },
39//! # };
40//! #
41//! pub struct App {
42//! window: Option<Arc<Window>>,
43//! backend: Option<Terminal<WgpuBackend<'static, 'static>>>,
44//! }
45//!
46//! impl ApplicationHandler for App {
47//! fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
48//! self.window = Some(Arc::new(
49//! event_loop
50//! .create_window(WindowAttributes::default())
51//! .unwrap(),
52//! ));
53//!
54//! let size = self.window.as_ref().unwrap().inner_size();
55//!
56//! self.backend = Some(
57//! Terminal::new(
58//! futures_lite::future::block_on(
59//! Builder::from_font(
60//! Font::new(include_bytes!("backend/fonts/CascadiaMono-Regular.ttf"))
61//! .unwrap(),
62//! )
63//! .with_width_and_height(Dimensions {
64//! width: NonZeroU32::new(size.width).unwrap(),
65//! height: NonZeroU32::new(size.height).unwrap(),
66//! })
67//! .build_with_target(self.window.as_ref().unwrap().clone()),
68//! )
69//! .unwrap(),
70//! )
71//! .unwrap(),
72//! );
73//!
74//! self.window.as_ref().unwrap().request_redraw();
75//! }
76//!
77//! fn window_event(
78//! &mut self,
79//! event_loop: &winit::event_loop::ActiveEventLoop,
80//! _window_id: winit::window::WindowId,
81//! event: winit::event::WindowEvent,
82//! ) {
83//! if let WindowEvent::CloseRequested = event {
84//! event_loop.exit();
85//! return;
86//! }
87//!
88//! let Some(terminal) = self.backend.as_mut() else {
89//! return;
90//! };
91//!
92//! if let WindowEvent::Resized(size) = event {
93//! terminal.backend_mut().resize(size.width, size.height);
94//! }
95//!
96//! terminal
97//! .draw(|f| {
98//! f.render_widget(
99//! Paragraph::new(Line::from("Hello World!")).block(Block::bordered()),
100//! f.area(),
101//! );
102//! })
103//! .unwrap();
104//!
105//! self.window.as_ref().unwrap().request_redraw();
106//! }
107//! }
108//! ```
109//!
110//! # Limitations
111//! 1. No cursor rendering.
112//! - The location of the cursor is tracked, and operations using it should
113//! behave as expected, but the cursor is not rendered to the screen.
114//! 2. Attempting to render more unique (utf8 character * BOLD|ITALIC)
115//! characters than can fit in the cache in a single draw call will cause
116//! incorrect rendering. This is ~3750 characters at the default font size
117//! with most fonts. If you need more than this, file a bug and I'll do the
118//! work to make rendering handle an unbounded number of unique characters.
119//! To put that in perspective, rendering every printable ascii character in
120//! every combination of styles would take (95 * 4) 380 cache entries or ~10%
121//! of the cache.
122
123pub(crate) mod backend;
124pub(crate) mod colors;
125pub(crate) mod fonts;
126pub mod shaders;
127pub(crate) mod utils;
128
129pub use ratatui;
130use thiserror::Error;
131pub use wgpu;
132
133#[macro_use]
134extern crate log;
135
136/// Represents the various errors that can occur during operation.
137#[derive(Debug, Error)]
138pub enum Error {
139 /// Backend creation failed because the device request failed.
140 #[error("{0}")]
141 DeviceRequestFailed(wgpu::RequestDeviceError),
142 /// Backend creation failed because creating the surface failed.
143 #[error("{0}")]
144 SurfaceCreationFailed(wgpu::CreateSurfaceError),
145 /// Backend creation failed because wgpu didn't provide an
146 /// [`Adapter`](wgpu::Adapter)
147 #[error("{0}")]
148 AdapterRequestFailed(wgpu::RequestAdapterError),
149 /// Backend creation failed because the default surface configuration
150 /// couldn't be loaded.
151 #[error("Failed to get default Surface configuration from wgpu.")]
152 SurfaceConfigurationRequestFailed,
153}
154
155pub type Result<T> = ::std::result::Result<T, Error>;
156
157#[cfg(feature = "ahash")]
158type RandomState = ahash::RandomState;
159#[cfg(not(feature = "ahash"))]
160type RandomState = std::hash::RandomState;
161
162pub use backend::{
163 builder::Builder,
164 wgpu_backend::WgpuBackend,
165 Dimensions,
166 PostProcessor,
167 RenderSurface,
168 RenderTexture,
169 Viewport,
170};
171pub use fonts::{
172 Font,
173 Fonts,
174};