orinium_browser/browser/core/ui/
renderer.rs1use std::collections::HashMap;
5
6use crate::browser::core::ui::TabId;
7use crate::engine::renderer_model::{AffineTransform, DrawCommand, FillRule, Rect, rect_path};
8use crate::platform::renderer::gpu::GpuRenderer;
9
10use super::{BasicChrome, BasicContextMenu, Chrome, ContextMenu, RenderState};
11use crate::browser::core::tab::Tab;
12
13#[derive(Debug)]
24pub struct BrowserRenderer {
25 pub render_state: RenderState,
27 pub chrome: Box<dyn Chrome>,
29 pub menu: Box<dyn ContextMenu>,
31}
32
33impl Default for BrowserRenderer {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl BrowserRenderer {
40 pub fn new() -> Self {
42 Self::with_chrome(Box::new(BasicChrome::new()))
43 }
44
45 pub fn with_chrome(chrome: Box<dyn Chrome>) -> Self {
47 Self::with_chrome_and_menu(chrome, Box::new(BasicContextMenu::new()))
48 }
49
50 pub fn with_window(window_size: (u32, u32), scale_factor: f64, window_title: String) -> Self {
52 Self {
53 render_state: RenderState::new(window_size, scale_factor, window_title),
54 chrome: Box::new(BasicChrome::new()),
55 menu: Box::new(BasicContextMenu::new()),
56 }
57 }
58
59 pub fn with_chrome_and_menu(chrome: Box<dyn Chrome>, menu: Box<dyn ContextMenu>) -> Self {
61 Self {
62 render_state: RenderState::default(),
63 chrome,
64 menu,
65 }
66 }
67
68 pub fn set_window(&mut self, window_size: (u32, u32), scale_factor: f64, window_title: String) {
70 self.render_state.window_size = window_size;
71 self.render_state.scale_factor = scale_factor;
72 self.render_state.window_title = window_title;
73 }
74
75 pub fn rebuild(&mut self, tabs: &mut HashMap<TabId, Tab>, active_id: Option<TabId>) {
78 let (width, height) = self.render_state.viewport();
79
80 let Rect {
81 x,
82 y,
83 width: content_width,
84 height: content_height,
85 } = self.chrome.content_rect(width, height);
86
87 let mut draw_commands = std::mem::take(&mut self.render_state.draw_commands);
89 draw_commands.clear();
90
91 draw_commands.push(DrawCommand::PushClip {
93 path: rect_path(x, y, content_width, content_height),
94 rule: FillRule::NonZero,
95 });
96 draw_commands.push(DrawCommand::PushTransform {
97 transform: AffineTransform::translate(x, y),
98 });
99
100 let title = if let Some(active_tab) = active_id
101 && let Some(tab) = tabs.get_mut(&active_tab)
102 {
103 let url = tab.document_url().map(|url| url.to_string());
105 self.chrome.sync_url(url.as_deref());
106
107 tab.draw(&mut draw_commands, content_width, content_height);
108
109 tab.title()
110 } else {
111 None
112 };
113
114 draw_commands.push(DrawCommand::PopTransform);
115 draw_commands.push(DrawCommand::PopClip);
116
117 self.chrome.draw(&mut draw_commands, width, height);
119
120 self.menu.draw(&mut draw_commands, width, height);
122
123 self.render_state.draw_commands = draw_commands;
125
126 if let Some(title) = title {
127 self.render_state.window_title = title;
128 }
129 }
130
131 pub fn apply_draw_commands(&self, gpu: &mut GpuRenderer) {
133 gpu.parse_draw_commands(&self.render_state.draw_commands);
134 }
135
136 pub fn redraw(
138 &mut self,
139 tabs: &mut HashMap<TabId, Tab>,
140 active_id: Option<TabId>,
141 gpu: &mut GpuRenderer,
142 ) {
143 self.rebuild(tabs, active_id);
144 self.apply_draw_commands(gpu);
145 if let Err(e) = gpu.render() {
146 log::error!(target: "BrowserRenderer::redraw", "Render error occurred: {}", e);
147 }
148 }
149}