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(
48//! &mut self,
49//! event_loop: &winit::event_loop::ActiveEventLoop,
50//! ) {
51//! self.window = Some(Arc::new(
52//! event_loop
53//! .create_window(WindowAttributes::default())
54//! .unwrap(),
55//! ));
56//!
57//! let size = self.window.as_ref().unwrap().inner_size();
58//!
59//! self.backend = Some(
60//! Terminal::new(
61//! futures_lite::future::block_on(
62//! Builder::from_font(
63//! Font::new(include_bytes!("backend/fonts/CascadiaMono-Regular.ttf"))
64//! .unwrap(),
65//! )
66//! .with_width_and_height(Dimensions {
67//! width: NonZeroU32::new(size.width).unwrap(),
68//! height: NonZeroU32::new(size.height).unwrap(),
69//! })
70//! .build_with_target(self.window.as_ref().unwrap().clone()),
71//! )
72//! .unwrap(),
73//! )
74//! .unwrap(),
75//! );
76//!
77//! self.window.as_ref().unwrap().request_redraw();
78//! }
79//!
80//! fn window_event(
81//! &mut self,
82//! event_loop: &winit::event_loop::ActiveEventLoop,
83//! _window_id: winit::window::WindowId,
84//! event: winit::event::WindowEvent,
85//! ) {
86//! if let WindowEvent::CloseRequested = event {
87//! event_loop.exit();
88//! return;
89//! }
90//!
91//! let Some(terminal) = self.backend.as_mut() else {
92//! return;
93//! };
94//!
95//! if let WindowEvent::Resized(size) = event {
96//! terminal.backend_mut().resize(size.width, size.height);
97//! }
98//!
99//! terminal
100//! .draw(|f| {
101//! f.render_widget(
102//! Paragraph::new(Line::from("Hello World!")).block(Block::bordered()),
103//! f.area(),
104//! );
105//! })
106//! .unwrap();
107//!
108//! self.window.as_ref().unwrap().request_redraw();
109//! }
110//! }
111//! ```
112//!
113//! # Limitations
114//! 1. No cursor rendering.
115//! - The location of the cursor is tracked, and operations using it should
116//! behave as expected, but the cursor is not rendered to the screen.
117//! 2. Attempting to render more unique (utf8 character * BOLD|ITALIC)
118//! characters than can fit in the cache in a single draw call will cause
119//! incorrect rendering. This is ~3750 characters at the default font size
120//! with most fonts. If you need more than this, file a bug and I'll do the
121//! work to make rendering handle an unbounded number of unique characters.
122//! To put that in perspective, rendering every printable ascii character in
123//! every combination of styles would take (95 * 4) 380 cache entries or ~10%
124//! of the cache.
125
126pub(crate) mod backend;
127pub(crate) mod colors;
128pub(crate) mod fonts;
129pub mod shaders;
130pub(crate) mod utils;
131
132pub use ratatui_core;
133use thiserror::Error;
134pub use wgpu;
135
136#[macro_use]
137extern crate log;
138
139/// Represents the various errors that can occur during operation.
140#[derive(Debug, Error)]
141pub enum Error {
142 /// Backend creation failed because the device request failed.
143 #[error("{0}")]
144 DeviceRequestFailed(wgpu::RequestDeviceError),
145 /// Backend creation failed because creating the surface failed.
146 #[error("{0}")]
147 SurfaceCreationFailed(wgpu::CreateSurfaceError),
148 /// Backend creation failed because wgpu didn't provide an
149 /// [`Adapter`](wgpu::Adapter)
150 #[error("{0}")]
151 AdapterRequestFailed(wgpu::RequestAdapterError),
152 /// Backend creation failed because the default surface configuration
153 /// couldn't be loaded.
154 #[error("Failed to get default Surface configuration from wgpu.")]
155 SurfaceConfigurationRequestFailed,
156}
157
158pub type Result<T> = ::std::result::Result<T, Error>;
159
160#[cfg(feature = "ahash")]
161type RandomState = ahash::RandomState;
162#[cfg(not(feature = "ahash"))]
163type RandomState = std::hash::RandomState;
164
165pub use backend::builder::Builder;
166pub use backend::wgpu_backend::WgpuBackend;
167pub use backend::Dimensions;
168pub use backend::PostProcessor;
169pub use backend::RenderSurface;
170pub use backend::RenderTexture;
171pub use backend::Viewport;
172pub use colors::ColorTable;
173pub use fonts::Font;
174pub use fonts::Fonts;