1use super::{atlas, basic};
9use kas::cast::Cast;
10use kas::draw::{
11 AllocError, DrawImpl, DrawSharedImpl, PassId, PassType, UploadError, WindowCommon,
12};
13use kas::draw::{ImageFormat, ImageId, color};
14use kas::geom::{Quad, Size, Vec2};
15use kas::prelude::{Offset, Rect};
16use kas::text::{self};
17
18#[derive(Debug)]
19struct ClipRegion {
20 rect: Rect,
21 offset: Offset,
22 order: u64,
23}
24
25impl Default for ClipRegion {
26 fn default() -> Self {
27 ClipRegion {
28 rect: Rect::ZERO,
29 offset: Offset::ZERO,
30 order: 1,
31 }
32 }
33}
34
35kas::impl_scope! {
36 #[impl_default]
37 pub struct Draw {
38 pub(crate) common: WindowCommon,
39 images: atlas::Window,
40 clip_regions: Vec<ClipRegion> = vec![Default::default()],
41 basic: basic::Draw,
42 }
43}
44
45impl DrawImpl for Draw {
46 fn common_mut(&mut self) -> &mut WindowCommon {
47 &mut self.common
48 }
49
50 fn new_pass(
51 &mut self,
52 parent_pass: PassId,
53 rect: Rect,
54 offset: Offset,
55 class: PassType,
56 ) -> PassId {
57 let parent = match class {
58 PassType::Clip => &self.clip_regions[parent_pass.pass()],
59 PassType::Overlay => {
60 &self.clip_regions[0]
63 }
64 };
65 let order = match class {
66 PassType::Clip => (parent.order << 4) + 1,
67 PassType::Overlay => (parent.order << 16) + 1,
68 };
69 let rect = rect - parent.offset;
70 let offset = offset + parent.offset;
71 let rect = rect.intersection(&parent.rect).unwrap_or(Rect::ZERO);
72 let pass = self.clip_regions.len().cast();
73 self.clip_regions.push(ClipRegion {
74 rect,
75 offset,
76 order,
77 });
78 PassId::new(pass)
79 }
80
81 #[inline]
82 fn get_clip_rect(&self, pass: PassId) -> Rect {
83 let region = &self.clip_regions[pass.pass()];
84 region.rect + region.offset
85 }
86
87 fn rect(&mut self, pass: PassId, rect: Quad, col: color::Rgba) {
88 self.basic.rect(pass, rect, col);
89 }
90
91 #[inline]
92 fn frame(&mut self, pass: PassId, outer: Quad, inner: Quad, col: color::Rgba) {
93 self.basic.frame(pass, outer, inner, col);
94 }
95
96 #[inline]
97 fn line(&mut self, pass: PassId, p1: Vec2, p2: Vec2, width: f32, col: color::Rgba) {
98 self.basic.line(pass, p1, p2, width, col);
99 }
100}
101
102impl Draw {
103 pub fn resize(&mut self, size: Size) {
104 self.clip_regions[0].rect.size = size;
105 }
106
107 pub fn render(&mut self, shared: &mut Shared, buffer: &mut [u32], size: (usize, usize)) {
108 shared.images.prepare(&mut shared.text);
109
110 let mut passes: Vec<_> = self.clip_regions.iter().enumerate().collect();
112 passes.sort_by_key(|pass| pass.1.order);
114
115 for (pass, clip) in passes.drain(..) {
116 self.basic
117 .render(pass, buffer, size, clip.rect, clip.offset);
118 self.images
119 .render(&shared.images, pass, buffer, size, clip.rect, clip.offset);
120 }
121
122 self.clip_regions.truncate(1);
124 }
125}
126
127pub struct Shared {
128 images: atlas::Shared,
129 text: kas::text::raster::State,
130}
131
132impl Default for Shared {
133 fn default() -> Self {
134 Shared {
135 images: atlas::Shared::new(),
136 text: Default::default(),
137 }
138 }
139}
140
141impl DrawSharedImpl for Shared {
142 type Draw = Draw;
143
144 #[inline]
145 fn max_texture_dimension_2d(&self) -> u32 {
146 atlas::MAX_TEX_SIZE.cast()
147 }
148
149 #[inline]
150 fn set_raster_config(&mut self, config: &kas::config::RasterConfig) {
151 self.images.set_raster_config(config);
152 self.text.set_raster_config(config);
153 }
154
155 #[inline]
156 fn image_alloc(&mut self, format: ImageFormat, size: Size) -> Result<ImageId, AllocError> {
157 self.images.alloc(format, size)
158 }
159
160 #[inline]
161 fn image_upload(&mut self, id: ImageId, data: &[u8]) -> Result<(), UploadError> {
162 self.images.upload(id, data)
163 }
164
165 #[inline]
166 fn image_free(&mut self, id: ImageId) {
167 self.images.free(id);
168 }
169
170 #[inline]
171 fn image_size(&self, id: ImageId) -> Option<Size> {
172 self.images.image_size(id)
173 }
174
175 fn draw_image(&self, draw: &mut Draw, pass: PassId, id: ImageId, rect: Quad) {
176 if let Some((atlas, tex)) = self.images.get_im_atlas_coords(id) {
177 draw.images.rect(pass, atlas, tex, rect);
178 }
179 }
180
181 #[inline]
182 fn draw_text(
183 &mut self,
184 draw: &mut Draw,
185 pass: PassId,
186 pos: Vec2,
187 bb: Quad,
188 text: &text::TextDisplay,
189 col: color::Rgba,
190 ) {
191 let time = std::time::Instant::now();
192 self.text
193 .text(&mut self.images, &mut draw.images, pass, pos, bb, text, col);
194 draw.common.report_dur_text(time.elapsed());
195 }
196
197 fn draw_text_effects(
198 &mut self,
199 draw: &mut Draw,
200 pass: PassId,
201 pos: Vec2,
202 bb: Quad,
203 text: &text::TextDisplay,
204 colors: &[color::Rgba],
205 effects: &[text::Effect],
206 ) {
207 let time = std::time::Instant::now();
208 self.text.text_effects(
209 &mut self.images,
210 &mut draw.images,
211 pass,
212 pos,
213 bb,
214 text,
215 colors,
216 effects,
217 |quad, col| {
218 draw.basic.rect(pass, quad, col);
219 },
220 );
221 draw.common.report_dur_text(time.elapsed());
222 }
223}