1use alloc::rc::Rc;
27use alloc::vec::Vec;
28use core::sync::atomic::{AtomicBool, Ordering};
29
30use super::consts::*;
31use super::Ui;
32use gfx::shapes::Shapes;
33use gfx::{Dc, Surface};
34use text::Text;
35
36pub(crate) const CAPS_MAIN: [u32; L_COUNT] = [1024 * 1024, 256 * 1024, 256 * 1024, 256 * 1024];
38#[allow(dead_code)] pub(crate) const CAPS_SMALL: [u32; L_COUNT] = [256 * 1024, 64 * 1024, 128 * 1024, 16 * 1024];
40
41pub struct Gfx<'a> {
44 pub dc: &'a mut Dc,
45 pub sf: &'a mut Surface,
46 pub text: &'a mut Text,
47}
48
49impl Gfx<'_> {
50 pub fn shapes(&mut self) -> Shapes<'_> {
52 Shapes { dc: &mut *self.dc, sf: &mut *self.sf, path: &mut self.text.path, ras: &mut self.text.ras }
53 }
54}
55
56pub trait Draw {
60 fn draw(&self, g: &mut Gfx, r: [i32; 4]);
61}
62
63pub type DrawRef = Rc<dyn Draw>;
64
65pub type IconHook = Rc<dyn Fn(&mut Gfx, u32, i32, i32, i32, u32) -> bool>;
68
69#[derive(Clone)]
71#[non_exhaustive]
72pub enum Cmd {
73 Rect { x: i32, y: i32, w: i32, h: i32, c: u32 },
74 RRect { x: i32, y: i32, w: i32, h: i32, r: u16, t: u16, fill: u32, stroke: u32, stroke2: u32 },
77 PanelFx { x: i32, y: i32, w: i32, h: i32, r: i32, t: i32, fill: u32, stroke: u32 },
79 Text { x: i32, y: i32, font: u16, size: i32, c: u32, maxw: i32, s: Vec<u8> },
81 Icon { x: i32, y: i32, cp: u32, size: i32, c: u32 },
83 Image { x: i32, y: i32, w: i32, h: i32, sf: Rc<Surface>, ver: u32 },
84 Clip { x: i32, y: i32, w: i32, h: i32 },
85 Unclip,
86 Circle { x: i32, y: i32, r: i32, t: i32, c: u32 },
88 Line { x0: i32, y0: i32, x1: i32, y1: i32, w: i32, c: u32 },
90 Custom { x: i32, y: i32, w: i32, h: i32, f: Option<DrawRef>, user: usize, ver: u32 },
91 Shadow { x: i32, y: i32, w: i32, h: i32, r: i32, depth: i32, c: u32 },
92}
93
94impl Cmd {
95 fn size(&self) -> u32 {
97 let n = match self {
98 Cmd::Rect { .. } | Cmd::Icon { .. } | Cmd::Circle { .. } | Cmd::Clip { .. } => 24,
99 Cmd::RRect { .. } | Cmd::Image { .. } => 40,
100 Cmd::PanelFx { .. } => 40,
101 Cmd::Text { s, .. } => 28 + s.len() as u32,
102 Cmd::Unclip => 8,
103 Cmd::Line { .. } | Cmd::Shadow { .. } => 32,
104 Cmd::Custom { .. } => 48,
105 };
106 (n + 7) & !7
107 }
108}
109
110pub(crate) struct W {
112 pub(crate) layers: [Vec<Cmd>; L_COUNT],
113 pub(crate) len: [u32; L_COUNT],
115 pub(crate) cap: [u32; L_COUNT],
116 pub(crate) layer: usize,
117 pub(crate) dcol: u32,
118 pub(crate) overflow: bool,
119}
120
121impl W {
122 pub(crate) fn new(caps: &[u32; L_COUNT]) -> W {
124 W {
125 layers: Default::default(),
126 len: [0; L_COUNT],
127 cap: *caps,
128 layer: 0,
129 dcol: 0xFF00_0000,
130 overflow: false,
131 }
132 }
133}
134
135struct Fnv(u64);
137
138impl Fnv {
139 fn new() -> Fnv {
140 Fnv(0xCBF2_9CE4_8422_2325)
141 }
142 fn bytes(&mut self, b: &[u8]) {
143 for &x in b {
144 self.0 ^= x as u64;
145 self.0 = self.0.wrapping_mul(0x0000_0100_0000_01B3);
146 }
147 }
148 fn u32(&mut self, v: u32) {
149 self.bytes(&v.to_le_bytes());
150 }
151 fn i32(&mut self, v: i32) {
152 self.bytes(&v.to_le_bytes());
153 }
154 fn u64(&mut self, v: u64) {
155 self.bytes(&v.to_le_bytes());
156 }
157}
158
159pub(crate) fn cmd_hash(c: &Cmd) -> u64 {
162 let (body, x, y, _) = cmd_parts(c);
163 pos_mix(body, x as i64, y as i64)
164}
165
166#[inline]
169pub(crate) fn pos_mix(body: u64, x: i64, y: i64) -> u64 {
170 const K: u64 = 0x9E37_79B9_7F4A_7C15;
171 let h = (body ^ x as u64).wrapping_mul(K);
172 let h = (h.rotate_left(29) ^ y as u64).wrapping_mul(K);
173 h ^ h >> 31
174}
175
176pub(crate) fn cmd_parts(c: &Cmd) -> (u64, i32, i32, u32) {
181 let mut h = Fnv::new();
182 let size = c.size();
183 let head = |h: &mut Fnv, t: u8, argb: u32| {
184 h.bytes(&[t, 0]);
185 h.bytes(&(size as u16).to_le_bytes());
186 h.u32(argb);
187 };
188 let (x, y, sh) = match *c {
189 Cmd::Rect { x, y, w, h: hh, c } => {
190 head(&mut h, 1, c);
191 for v in [w, hh] {
192 h.i32(v);
193 }
194 (x, y, 0)
195 }
196 Cmd::RRect { x, y, w, h: hh, r, t, fill, stroke, stroke2 } => {
197 head(&mut h, 2, fill);
198 for v in [w, hh] {
199 h.i32(v);
200 }
201 h.bytes(&r.to_le_bytes());
202 h.bytes(&t.to_le_bytes());
203 h.u32(stroke);
204 h.u32(stroke2);
205 (x, y, 0)
206 }
207 Cmd::PanelFx { x, y, w, h: hh, r, t, fill, stroke } => {
208 head(&mut h, 12, fill);
209 for v in [w, hh, r, t] {
210 h.i32(v);
211 }
212 h.u32(stroke);
213 (x, y, 8)
214 }
215 Cmd::Text { x, y, font, size: sz, c, maxw, ref s } => {
216 head(&mut h, 3, c);
217 h.bytes(&font.to_le_bytes());
218 h.bytes(&(s.len() as u16).to_le_bytes());
219 h.i32(sz);
220 h.i32(maxw);
221 h.bytes(s);
222 (x, y, 0)
223 }
224 Cmd::Icon { x, y, cp, size: sz, c } => {
225 head(&mut h, 4, c);
226 h.u32(cp);
227 h.i32(sz);
228 (x, y, 0)
229 }
230 Cmd::Image { x, y, w, h: hh, ref sf, ver } => {
231 head(&mut h, 5, 0);
232 for v in [w, hh] {
233 h.i32(v);
234 }
235 h.u64(Rc::as_ptr(sf) as usize as u64);
236 h.u32(ver);
237 (x, y, 0)
238 }
239 Cmd::Clip { x, y, w, h: hh } => {
240 head(&mut h, 6, 0);
241 for v in [w, hh] {
242 h.i32(v);
243 }
244 (x, y, 0)
245 }
246 Cmd::Unclip => {
247 head(&mut h, 7, 0);
248 (0, 0, 0)
249 }
250 Cmd::Circle { x, y, r, t, c } => {
251 head(&mut h, 8, c);
252 for v in [r, t] {
253 h.i32(v);
254 }
255 (x, y, 8)
256 }
257 Cmd::Line { x0, y0, x1, y1, w, c } => {
258 head(&mut h, 9, c);
259 for v in [x1.wrapping_sub(x0), y1.wrapping_sub(y0), w] {
260 h.i32(v);
261 }
262 (x0, y0, 8)
263 }
264 Cmd::Custom { x, y, w, h: hh, ref f, user, ver } => {
265 head(&mut h, 10, 0);
266 for v in [w, hh] {
267 h.i32(v);
268 }
269 h.u64(f.as_ref().map_or(0, |f| Rc::as_ptr(f) as *const () as usize as u64));
270 h.u64(user as u64);
271 h.u32(ver);
272 (x, y, 0)
273 }
274 Cmd::Shadow { x, y, w, h: hh, r, depth, c } => {
275 head(&mut h, 11, c);
276 for v in [w, hh, r, depth] {
277 h.i32(v);
278 }
279 (x, y, 0)
280 }
281 };
282 (h.0, x, y, sh)
283}
284
285pub(crate) fn cmd_bbox(c: &Cmd) -> Option<[i32; 4]> {
288 Some(match *c {
289 Cmd::PanelFx { x, y, w, h, .. } => [x >> 8, y >> 8,
290 ((x as i64 + w as i64 + 255) >> 8) as i32,
291 ((y as i64 + h as i64 + 255) >> 8) as i32],
292 Cmd::Text { x, y, size, maxw, ref s, .. } => {
293 let px = ((size as u32) >> 8).wrapping_add(1) as i32;
295 let x0 = x.wrapping_sub(2);
296 let tw = if maxw != 0 { maxw } else { (s.len() as i32).wrapping_mul(px) };
297 let half = ((px as u32) >> 1) as i32;
298 [x0, y.wrapping_sub(half.wrapping_add(px)), x0.wrapping_add(tw).wrapping_add(4), y.wrapping_add(half).wrapping_add(1)]
299 }
300 Cmd::Icon { x, y, size, .. } => {
301 let s = ((size as u32) >> 8).wrapping_add(2) as i32; let (x0, y0) = (x.wrapping_sub(1), y.wrapping_sub(1));
303 [x0, y0, x0.wrapping_add(s), y0.wrapping_add(s)]
304 }
305 Cmd::Circle { x, y, r, t, .. } => {
306 let d = (r.wrapping_add(t) >> 8).wrapping_add(2);
308 let (cx, cy) = (x >> 8, y >> 8);
309 [cx.wrapping_sub(d), cy.wrapping_sub(d), cx.wrapping_add(d).wrapping_add(1), cy.wrapping_add(d).wrapping_add(1)]
310 }
311 Cmd::Line { x0, y0, x1, y1, w, .. } => {
312 let d = (w >> 8).wrapping_add(2); [
314 (x0.min(x1) >> 8).wrapping_sub(d),
315 (y0.min(y1) >> 8).wrapping_sub(d),
316 (x0.max(x1) >> 8).wrapping_add(d).wrapping_add(1),
317 (y0.max(y1) >> 8).wrapping_add(d).wrapping_add(1),
318 ]
319 }
320 Cmd::Shadow { x, y, w, h, depth: d, .. } => {
321 [x.wrapping_sub(d), y.wrapping_sub(d), x.wrapping_add(w).wrapping_add(d), y.wrapping_add(h).wrapping_add(d).wrapping_add(d)]
323 }
324 Cmd::Clip { .. } | Cmd::Unclip => return None,
325 Cmd::Rect { x, y, w, h, .. }
326 | Cmd::RRect { x, y, w, h, .. }
327 | Cmd::Image { x, y, w, h, .. }
328 | Cmd::Custom { x, y, w, h, .. } => [x, y, x.wrapping_add(w), y.wrapping_add(h)],
329 })
330}
331
332pub(crate) static ICON_PAINTED: AtomicBool = AtomicBool::new(false);
336
337fn cmd_visible(c: &Cmd, dc: &Dc) -> bool {
339 let Some(b) = cmd_bbox(c) else { return true };
340 let k = dc.clip;
341 !(b[0] >= k[2] || b[2] <= k[0] || b[1] >= k[3] || b[3] <= k[1])
342}
343
344#[allow(clippy::too_many_arguments)]
348pub(crate) fn render_layer(list: &[Cmd], from: usize, dc: &mut Dc, sf: &mut Surface, text: &mut Text, hook: &Option<IconHook>,
349 icon_style: (&dyn crate::Style, u32, bool, u32, u32)) {
350 let mut depth = 0; for (i, c) in list.iter().enumerate() {
352 if !matches!(c, Cmd::Clip { .. } | Cmd::Unclip) && (i < from || !cmd_visible(c, dc)) {
353 continue;
354 }
355 match c {
356 &Cmd::PanelFx { x, y, w, h, r, t, fill, stroke } => {
357 let mut sh = Shapes { dc: &mut *dc, sf: &mut *sf, path: &mut text.path, ras: &mut text.ras };
358 sh.panel_fx(x, y, w, h, r, t, fill, stroke);
359 }
360 &Cmd::Rect { x, y, w, h, c } => {
361 dc.set_color(c);
362 dc.fill(sf, x, y, w, h);
363 }
364 &Cmd::RRect { x, y, w, h, r, t, fill, stroke, stroke2 } => {
365 let mut sh = Shapes { dc: &mut *dc, sf: &mut *sf, path: &mut text.path, ras: &mut text.ras };
366 draw_rrect(&mut sh, [x, y, w, h], r as i32, t as i32, fill, stroke, stroke2);
367 }
368 Cmd::Text { x, y, font, size, c, maxw, s } => {
369 dc.set_color(*c);
370 text.set_font(*font as u32, *size);
371 if *maxw != 0 {
372 dc.clip_push(*x, -100000, *maxw, 200000);
373 }
374 text.draw_n(dc, sf, *x, *y, s, s.len());
375 if *maxw != 0 {
376 dc.clip_pop();
377 }
378 }
379 &Cmd::Icon { x, y, cp, size, c } => {
380 if let Some(f) = hook {
381 let (tx, ty) = (x.wrapping_add(dc.ox), y.wrapping_add(dc.oy));
383 let mut g = Gfx { dc: &mut *dc, sf: &mut *sf, text: &mut *text };
384 if f(&mut g, cp, tx, ty, size, c) {
385 ICON_PAINTED.store(true, Ordering::Relaxed);
386 continue;
387 }
388 }
389 let (style, accent, dark, disabled, dpi) = icon_style;
390 let (tx, ty) = (x.wrapping_add(dc.ox), y.wrapping_add(dc.oy));
391 let mut g = Gfx { dc: &mut *dc, sf: &mut *sf, text: &mut *text };
392 if style.paint_icon(&mut g, cp, tx, ty, size, c, accent, dark, c == disabled, dpi) {
393 ICON_PAINTED.store(true, Ordering::Relaxed);
394 continue;
395 }
396 dc.set_color(c);
397 text.icon_draw(dc, sf, cp, x, y, size);
398 }
399 Cmd::Image { x, y, w, h, sf: src, .. } => {
400 dc.blit_scaled(sf, src, *x, *y, *w, *h);
401 }
402 &Cmd::Clip { x, y, w, h } => {
403 dc.clip_push(x, y, w, h);
404 depth += 1;
405 }
406 Cmd::Unclip => {
407 if depth > 0 {
408 dc.clip_pop();
409 depth -= 1;
410 }
411 }
412 &Cmd::Circle { x, y, r, t, c } => {
413 dc.set_color(c);
414 let mut sh = Shapes { dc: &mut *dc, sf: &mut *sf, path: &mut text.path, ras: &mut text.ras };
415 if t != 0 {
416 sh.stroke_circle_fx(x, y, r, t);
417 } else {
418 sh.fill_circle_fx(x, y, r);
419 }
420 }
421 &Cmd::Line { x0, y0, x1, y1, w, c } => {
422 dc.set_color(c);
423 let mut sh = Shapes { dc: &mut *dc, sf: &mut *sf, path: &mut text.path, ras: &mut text.ras };
424 sh.line_fx(x0, y0, x1, y1, w);
425 }
426 Cmd::Custom { x, y, w, h, f, .. } => {
427 dc.clip_push(*x, *y, *w, *h);
429 if let Some(f) = f {
430 let mut g = Gfx { dc: &mut *dc, sf: &mut *sf, text: &mut *text };
431 f.draw(&mut g, [*x, *y, *w, *h]);
432 }
433 dc.clip_pop();
434 }
435 &Cmd::Shadow { x, y, w, h, r, depth: d, c } => {
436 let mut sh = Shapes { dc: &mut *dc, sf: &mut *sf, path: &mut text.path, ras: &mut text.ras };
437 draw_shadow(&mut sh, [x, y, w, h], r, d, c);
438 }
439 }
440 }
441 while depth > 0 {
442 dc.clip_pop();
443 depth -= 1;
444 }
445}
446
447pub(crate) fn draw_rrect(sh: &mut Shapes, b: [i32; 4], r: i32, t: i32, fill: u32, stroke: u32, stroke2: u32) {
450 let [x, y, w, h] = b;
451 if fill & 0xFF00_0000 != 0 {
452 sh.dc.set_color(fill);
453 sh.fill_rrect(x, y, w, h, r);
454 }
455 if t == 0 {
456 return;
457 }
458 if stroke & 0xFF00_0000 != 0 {
459 sh.dc.set_color(stroke);
460 sh.stroke_rrect(x, y, w, h, r, t);
461 }
462 if stroke2 != stroke && stroke2 & 0xFF00_0000 != 0 {
464 sh.dc.set_color(stroke2);
465 let band = r.max(t);
466 sh.dc.clip_push(x, y.wrapping_add(h).wrapping_sub(band), w, band);
467 sh.stroke_rrect(x, y, w, h, r, t);
468 sh.dc.clip_pop();
469 }
470}
471
472pub(crate) fn draw_shadow(sh: &mut Shapes, b: [i32; 4], r: i32, d: i32, c: u32) {
475 let [x, y, w, h] = b;
476 if d <= 0 {
477 return;
478 }
479 let base = c >> 24;
480 let down = (d as u32 / 3) as i32;
481 let mut i = d;
482 while i != 0 {
483 let a = base.wrapping_mul((d - i + 1) as u32) / ((d + d) as u32);
485 sh.dc.set_color((c & 0xFF_FFFF) | a << 24);
486 sh.fill_rrect(x - i, y - i + down, w + i * 2, h + i * 2, r + i);
487 i -= 1;
488 }
489}
490
491#[allow(dead_code)] fn translate(list: &mut [Cmd], dx: i32, dy: i32) {
495 for c in list.iter_mut() {
496 match c {
497 Cmd::Unclip => {}
498 Cmd::Circle { x, y, .. } | Cmd::PanelFx { x, y, .. } => {
499 *x = x.wrapping_add(dx << 8);
500 *y = y.wrapping_add(dy << 8);
501 }
502 Cmd::Line { x0, y0, x1, y1, .. } => {
503 *x1 = x1.wrapping_add(dx << 8);
504 *y1 = y1.wrapping_add(dy << 8);
505 *x0 = x0.wrapping_add(dx << 8);
506 *y0 = y0.wrapping_add(dy << 8);
507 }
508 Cmd::Rect { x, y, .. }
509 | Cmd::RRect { x, y, .. }
510 | Cmd::Text { x, y, .. }
511 | Cmd::Icon { x, y, .. }
512 | Cmd::Image { x, y, .. }
513 | Cmd::Clip { x, y, .. }
514 | Cmd::Custom { x, y, .. }
515 | Cmd::Shadow { x, y, .. } => {
516 *x = x.wrapping_add(dx);
517 *y = y.wrapping_add(dy);
518 }
519 }
520 }
521}
522
523impl Ui {
524 pub(crate) fn cmd_reset(&mut self) {
526 let w = &mut self.wp.cmd;
527 for l in w.layers.iter_mut() {
528 l.clear();
529 }
530 w.len = [0; L_COUNT];
531 w.layer = 0;
532 w.dcol = 0xFF00_0000;
533 self.wp.rtl.reset();
534 self.wp.scopy.reset(); self.wp.canv.recs.clear(); }
537
538 pub fn cmd_layer(&mut self, l: u32) -> u32 {
540 let prev = self.wp.cmd.layer as u32;
541 self.wp.cmd.layer = (l & 3) as usize;
542 prev
543 }
544
545 fn push(&mut self, c: Cmd) {
547 let w = &mut self.wp.cmd;
548 let l = w.layer;
549 let n = w.len[l] + c.size();
550 if n > w.cap[l] {
551 w.overflow = true;
552 return;
553 }
554 w.len[l] = n;
555 w.layers[l].push(c);
556 }
557
558 pub fn draw_color(&mut self, argb: u32) {
560 self.wp.cmd.dcol = argb;
561 }
562
563 pub fn draw_color_get(&self) -> u32 {
565 self.wp.cmd.dcol
566 }
567
568 pub fn draw_rect(&mut self, x: i32, y: i32, w: i32, h: i32) {
570 let c = self.wp.cmd.dcol;
571 self.push(Cmd::Rect { x, y, w, h, c });
572 }
573
574 pub fn draw_rrect(&mut self, x: i32, y: i32, w: i32, h: i32, r: i32) {
576 let c = self.wp.cmd.dcol;
577 self.cmd_rrect(x, y, w, h, r, 0, c, 0, 0);
578 }
579
580 pub fn draw_frame(&mut self, x: i32, y: i32, w: i32, h: i32, r: i32, t: i32) {
582 let c = self.wp.cmd.dcol;
583 self.cmd_rrect(x, y, w, h, r, t, 0, c, c);
584 }
585
586 #[allow(clippy::too_many_arguments)]
589 pub fn cmd_rrect(&mut self, x: i32, y: i32, w: i32, h: i32, r: i32, t: i32, fill: u32, stroke: u32, stroke2: u32) {
590 let r = if self.look.rad_mode != 0 { self.look_radius(r, w, h) } else { r }; self.push(Cmd::RRect { x, y, w, h, r: r as u16, t: t as u16, fill, stroke, stroke2 });
592 }
593
594 #[allow(clippy::too_many_arguments)]
597 pub fn cmd_panel_fx(&mut self, x: i32, y: i32, w: i32, h: i32, r: i32, t: i32, fill: u32, stroke: u32) {
598 self.push(Cmd::PanelFx { x, y, w, h, r, t, fill, stroke });
599 }
600
601 pub fn draw_text(&mut self, x: i32, y: i32, s: &str, font_size: u32) {
603 let c = self.wp.cmd.dcol;
604 self.cmd_text(x, y, s.as_bytes(), font_size & 255, (font_size >> 8) as i32, c, 0);
605 }
606
607 #[allow(clippy::too_many_arguments)]
610 pub fn cmd_text(&mut self, x: i32, y: i32, s: &[u8], font: u32, size: i32, c: u32, maxw: i32) {
611 let mut n = s.len();
612 if n > 4000 {
613 n = 4000;
614 while n > 0 && s[n] & 0xC0 == 0x80 {
616 n -= 1;
617 }
618 }
619 self.push(Cmd::Text { x, y, font: font as u16, size, c, maxw, s: s[..n].to_vec() });
620 }
621
622 pub fn emit_text(&mut self, x: i32, y: i32, s: &str, c: u32) {
624 let (font, size) = self.text.get_font();
625 let b = s.as_bytes();
626 let n = b.iter().position(|&x| x == 0).unwrap_or(b.len());
627 self.cmd_text(x, y, &b[..n], font, size, c, 0);
628 }
629
630 pub fn draw_icon(&mut self, cp: u32, x: i32, y: i32, size: i32) {
632 let c = self.wp.cmd.dcol;
633 self.push(Cmd::Icon { x, y, cp, size, c });
634 }
635
636 pub fn draw_circle(&mut self, x: i32, y: i32, r: i32, t: i32) {
638 let c = self.wp.cmd.dcol;
639 self.push(Cmd::Circle { x, y, r, t, c });
640 }
641
642 pub fn draw_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, w: i32) {
644 let c = self.wp.cmd.dcol;
645 self.push(Cmd::Line { x0, y0, x1, y1, w, c });
646 }
647
648 pub fn draw_image(&mut self, sf: &Rc<Surface>, ver: u32, x: i32, y: i32, w: i32, h: i32) {
651 let w = if w == 0 { sf.w } else { w };
652 let h = if h == 0 { sf.h } else { h };
653 self.push(Cmd::Image { x, y, w, h, sf: sf.clone(), ver });
654 }
655
656 pub fn draw_clip(&mut self, x: i32, y: i32, w: i32, h: i32) {
658 self.push(Cmd::Clip { x, y, w, h });
659 }
660
661 pub fn draw_unclip(&mut self) {
663 self.push(Cmd::Unclip);
664 }
665
666 pub fn icon_hook(&mut self, f: Option<IconHook>) {
668 self.icon_hook = f;
669 }
670
671 #[allow(clippy::too_many_arguments)]
673 pub fn cmd_custom(&mut self, x: i32, y: i32, w: i32, h: i32, f: Option<DrawRef>, user: usize, ver: u32) {
674 self.push(Cmd::Custom { x, y, w, h, f, user, ver });
675 }
676
677 pub fn cmd_shadow(&mut self, x: i32, y: i32, w: i32, h: i32, r: i32, depth: i32) {
679 let r = if self.look.rad_mode != 0 { self.look_radius(r, w, h) } else { r }; let c = self.wp.cmd.dcol;
681 self.push(Cmd::Shadow { x, y, w, h, r, depth, c });
682 }
683
684 pub(crate) fn render_all_to(&mut self, shadow: bool) {
687 self.render_from(shadow, 0, 0);
688 }
689
690 pub(crate) fn render_from(&mut self, shadow: bool, layer: usize, from: usize) {
693 let icon_style = (self.style, self.color(T_ACCENT), self.theme_dark, self.color(T_TEXT_DISABLED), self.wp.rt.dpi as u32);
694 let Ui { wp, dc, text, icon_hook, .. } = self;
695 let sf = if shadow { &mut wp.rt.shadow } else { &mut wp.rt.fb };
696 for (k, l) in wp.cmd.layers.iter().enumerate().skip(layer) {
697 render_layer(l, if k == layer { from } else { 0 }, dc, sf, text, icon_hook, icon_style);
698 }
699 }
700
701 #[allow(dead_code)] pub(crate) fn render_popup(&mut self, sf: &mut Surface, dx: i32, dy: i32) {
705 let icon_style = (self.style, self.color(T_ACCENT), self.theme_dark, self.color(T_TEXT_DISABLED), self.wp.rt.dpi as u32);
706 let Ui { wp, dc, text, icon_hook, .. } = self;
707 let layers = &mut wp.cmd.layers;
708 translate(&mut layers[L_POPUP as usize], dx, dy);
709 translate(&mut layers[L_TIP as usize], dx, dy);
710 render_layer(&layers[L_POPUP as usize], 0, dc, sf, text, icon_hook, icon_style);
711 render_layer(&layers[L_TIP as usize], 0, dc, sf, text, icon_hook, icon_style);
712 translate(&mut layers[L_POPUP as usize], -dx, -dy);
713 translate(&mut layers[L_TIP as usize], -dx, -dy);
714 }
715}