1use super::types::Coord;
2use crate::enums::{Align, Color, ColorDepth, Cursor, Font, FrameType, Shortcut};
3use crate::image::RgbImage;
4use crate::prelude::*;
5use crate::surface::ImageSurface;
6use crate::utils::FlString;
7use fltk_sys::draw::*;
8use std::ffi::{CStr, CString};
9use std::mem;
10use std::os::raw;
11
12bitflags::bitflags! {
13 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15 pub struct LineStyle: i32 {
16 const Solid = 0;
18 const Dash = 1;
20 const Dot = 2;
22 const DashDot = 3;
24 const DashDotDot = 4;
26 const CapFlat = 0x100;
28 const CapRound = 0x200;
30 const CapSquare = 0x300;
32 const JoinMiter = 0x1000;
34 const JoinRound = 0x2000;
36 const JoinBevel = 0x3000;
38 }
39}
40
41pub struct Region(pub(crate) *mut raw::c_void);
43
44#[derive(Debug)]
46pub struct Offscreen {
47 inner: *mut raw::c_void,
48}
49
50#[cfg(not(feature = "single-threaded"))]
51unsafe impl Sync for Offscreen {}
52#[cfg(not(feature = "single-threaded"))]
53unsafe impl Send for Offscreen {}
54
55impl PartialEq for Offscreen {
56 fn eq(&self, other: &Self) -> bool {
57 self.inner == other.inner
58 }
59}
60
61impl Eq for Offscreen {}
62
63impl Offscreen {
64 pub fn new(w: i32, h: i32) -> Option<Offscreen> {
66 unsafe {
67 let x = Fl_create_offscreen(w, h);
68 if x.is_null() {
69 None
70 } else {
71 Some(Offscreen { inner: x })
72 }
73 }
74 }
75
76 pub unsafe fn uninit() -> Offscreen {
80 Offscreen {
81 inner: std::ptr::null_mut(),
82 }
83 }
84
85 pub fn begin(&self) {
87 assert!(!self.inner.is_null());
88 unsafe { Fl_begin_offscreen(self.inner) }
89 }
90
91 pub fn end(&self) {
93 assert!(!self.inner.is_null());
94 unsafe { Fl_end_offscreen() }
95 }
96
97 pub fn copy(&self, x: i32, y: i32, w: i32, h: i32, src_x: i32, src_y: i32) {
99 assert!(!self.inner.is_null());
100 unsafe { Fl_copy_offscreen(x, y, w, h, self.inner, src_x, src_y) }
101 }
102
103 pub fn rescale(&mut self) {
105 assert!(!self.inner.is_null());
106 unsafe { Fl_rescale_offscreen(&mut self.inner) }
107 }
108
109 pub fn is_valid(&self) -> bool {
111 !self.inner.is_null()
112 }
113
114 pub unsafe fn shallow_copy(&self) -> Offscreen {
118 assert!(!self.inner.is_null());
119 Offscreen { inner: self.inner }
120 }
121}
122
123impl Drop for Offscreen {
124 fn drop(&mut self) {
125 unsafe { Fl_delete_offscreen(self.inner) }
126 }
127}
128
129pub fn show_colormap(old_color: Color) -> Color {
131 unsafe { mem::transmute(Fl_show_colormap(old_color.bits())) }
132}
133
134pub fn set_color_rgb(r: u8, g: u8, b: u8) {
136 unsafe { Fl_set_color_rgb(r, g, b) }
137}
138
139pub fn get_color() -> Color {
141 unsafe { mem::transmute(Fl_get_color()) }
142}
143
144pub fn draw_line(x1: i32, y1: i32, x2: i32, y2: i32) {
146 unsafe {
147 Fl_line(x1, y1, x2, y2);
148 }
149}
150
151pub fn draw_line2(pos1: Coord<i32>, pos2: Coord<i32>, pos3: Coord<i32>) {
153 unsafe { Fl_line2(pos1.0, pos1.1, pos2.0, pos2.1, pos3.0, pos3.1) }
154}
155
156pub fn draw_point(x: i32, y: i32) {
158 unsafe { Fl_point(x, y) }
159}
160
161pub fn draw_point2(pos: Coord<i32>) {
163 unsafe { Fl_point(pos.0, pos.1) }
164}
165
166pub fn draw_rect(x: i32, y: i32, w: i32, h: i32) {
168 unsafe { Fl_rect(x, y, w, h) }
169}
170
171pub fn draw_rect_with_color(x: i32, y: i32, w: i32, h: i32, color: Color) {
173 unsafe { Fl_rect_with_color(x, y, w, h, color.bits()) }
174}
175
176pub fn draw_loop(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
178 unsafe {
179 Fl_loop(x1, y1, x2, y2, x3, y3);
180 }
181}
182
183pub fn draw_loop2(pos1: Coord<i32>, pos2: Coord<i32>, pos3: Coord<i32>) {
185 unsafe { Fl_loop(pos1.0, pos1.1, pos2.0, pos2.1, pos3.0, pos3.1) }
186}
187
188pub fn draw_loop3(pos1: Coord<i32>, pos2: Coord<i32>, pos3: Coord<i32>, pos4: Coord<i32>) {
190 unsafe {
191 Fl_loop2(
192 pos1.0, pos1.1, pos2.0, pos2.1, pos3.0, pos3.1, pos4.0, pos4.1,
193 )
194 }
195}
196
197pub fn draw_rect_fill(x: i32, y: i32, w: i32, h: i32, color: Color) {
199 unsafe { Fl_rectf_with_color(x, y, w, h, color.bits()) }
200}
201
202pub fn draw_focus_rect(x: i32, y: i32, w: i32, h: i32) {
204 unsafe { Fl_focus_rect(x, y, w, h) }
205}
206
207pub fn set_draw_hex_color(color: u32) {
209 unsafe {
210 crate::app::open_display();
211 }
212 let (r, g, b) = crate::utils::hex2rgb(color);
213 unsafe { Fl_set_color_rgb(r, g, b) }
214}
215
216pub fn set_draw_rgb_color(r: u8, g: u8, b: u8) {
218 unsafe {
219 crate::app::open_display();
220 }
221 unsafe { Fl_set_color_rgb(r, g, b) }
222}
223
224pub fn set_draw_color(color: Color) {
226 unsafe {
227 crate::app::open_display();
228 }
229 unsafe { Fl_set_color_int(color.bits()) }
230}
231
232pub fn draw_circle(x: f64, y: f64, r: f64) {
234 unsafe {
235 Fl_circle(x, y, r);
236 }
237}
238
239pub fn draw_arc(x: i32, y: i32, width: i32, height: i32, a: f64, b: f64) {
241 unsafe {
242 Fl_arc(x, y, width, height, a, b);
243 }
244}
245
246pub fn draw_arc2(x: f64, y: f64, r: f64, start: f64, end: f64) {
248 unsafe { Fl_arc2(x, y, r, start, end) }
249}
250
251pub fn draw_pie(x: i32, y: i32, width: i32, height: i32, a: f64, b: f64) {
253 unsafe {
254 Fl_pie(x, y, width, height, a, b);
255 }
256}
257
258pub fn set_line_style(style: LineStyle, width: i32) {
265 unsafe {
266 crate::app::open_display();
267 Fl_line_style(
268 style.bits(),
269 width,
270 std::ptr::null_mut() as *mut std::os::raw::c_char,
271 );
272 }
273}
274
275pub fn push_clip(x: i32, y: i32, w: i32, h: i32) {
277 unsafe {
278 Fl_push_clip(x, y, w, h);
279 }
280}
281
282pub fn pop_clip() {
284 unsafe {
285 Fl_pop_clip();
286 }
287}
288
289pub fn set_clip_region(r: Region) {
291 assert!(!r.0.is_null());
292 unsafe { Fl_set_clip_region(r.0) }
293}
294
295pub fn clip_region() -> Region {
297 unsafe {
298 let ptr = Fl_clip_region();
299 assert!(!ptr.is_null());
300 Region(ptr)
301 }
302}
303
304pub fn push_no_clip() {
306 unsafe { Fl_push_no_clip() }
307}
308
309pub fn not_clipped(x: i32, y: i32, w: i32, h: i32) -> bool {
311 unsafe { Fl_not_clipped(x, y, w, h) != 0 }
312}
313
314pub fn restore_clip() {
316 unsafe { Fl_restore_clip() }
317}
318
319pub fn transform_x(x: f64, y: f64) -> f64 {
321 unsafe { Fl_transform_x(x, y) }
322}
323
324pub fn transform_y(x: f64, y: f64) -> f64 {
326 unsafe { Fl_transform_y(x, y) }
327}
328
329pub fn transform_dx(x: f64, y: f64) -> f64 {
331 unsafe { Fl_transform_dx(x, y) }
332}
333
334pub fn transform_dy(x: f64, y: f64) -> f64 {
336 unsafe { Fl_transform_dy(x, y) }
337}
338
339pub fn transformed_vertex(xf: f64, yf: f64) {
341 unsafe { Fl_transformed_vertex(xf, yf) }
342}
343
344pub fn draw_rectf(x: i32, y: i32, w: i32, h: i32) {
346 unsafe { Fl_rectf(x, y, w, h) }
347}
348
349pub fn draw_rectf_with_rgb(
351 x: i32,
352 y: i32,
353 width: i32,
354 height: i32,
355 color_r: u8,
356 color_g: u8,
357 color_b: u8,
358) {
359 unsafe { Fl_rectf_with_rgb(x, y, width, height, color_r, color_g, color_b) }
360}
361
362pub fn draw_polygon(x: i32, y: i32, x1: i32, y1: i32, x2: i32, y2: i32) {
364 unsafe { Fl_polygon(x, y, x1, y1, x2, y2) }
365}
366
367pub fn draw_polygon2(pos1: Coord<i32>, pos2: Coord<i32>, pos3: Coord<i32>) {
369 unsafe { Fl_polygon(pos1.0, pos1.1, pos2.0, pos2.1, pos3.0, pos3.1) }
370}
371
372pub fn draw_polygon3(pos1: Coord<i32>, pos2: Coord<i32>, pos3: Coord<i32>, pos4: Coord<i32>) {
374 unsafe {
375 Fl_polygon2(
376 pos1.0, pos1.1, pos2.0, pos2.1, pos3.0, pos3.1, pos4.0, pos4.1,
377 )
378 }
379}
380
381pub fn draw_curve(pos1: Coord<f64>, pos2: Coord<f64>, pos3: Coord<f64>, pos4: Coord<f64>) {
383 unsafe {
384 Fl_curve(
385 pos1.0, pos1.1, pos2.0, pos2.1, pos3.0, pos3.1, pos4.0, pos4.1,
386 )
387 }
388}
389
390pub fn draw_xyline(x: i32, y: i32, x1: i32) {
392 unsafe { Fl_xyline(x, y, x1) }
393}
394
395pub fn draw_xyline2(x: i32, y: i32, x1: i32, y2: i32) {
397 unsafe { Fl_xyline2(x, y, x1, y2) }
398}
399
400pub fn draw_xyline3(x: i32, y: i32, x1: i32, y2: i32, x3: i32) {
403 unsafe { Fl_xyline3(x, y, x1, y2, x3) }
404}
405
406pub fn draw_yxline(x: i32, y: i32, y1: i32) {
408 unsafe { Fl_yxline(x, y, y1) }
409}
410
411pub fn draw_yxline2(x: i32, y: i32, y1: i32, x2: i32) {
413 unsafe { Fl_yxline2(x, y, y1, x2) }
414}
415
416pub fn draw_yxline3(x: i32, y: i32, y1: i32, x2: i32, y3: i32) {
419 unsafe { Fl_yxline3(x, y, y1, x2, y3) }
420}
421
422pub fn push_matrix() {
424 unsafe { Fl_push_matrix() }
425}
426
427pub fn pop_matrix() {
429 unsafe { Fl_pop_matrix() }
430}
431
432pub fn scale_xy(x: f64, y: f64) {
434 unsafe { Fl_scale(x, y) }
435}
436
437pub fn scale(val: f64) {
439 unsafe { Fl_scale2(val) }
440}
441
442pub fn translate(x: f64, y: f64) {
444 unsafe { Fl_translate(x, y) }
445}
446
447pub fn rotate(d: f64) {
449 unsafe { Fl_rotate(d) }
450}
451
452pub fn mult_matrix(val_a: f64, val_b: f64, val_c: f64, val_d: f64, x: f64, y: f64) {
454 unsafe { Fl_mult_matrix(val_a, val_b, val_c, val_d, x, y) }
455}
456
457pub fn begin_points() {
459 unsafe { Fl_begin_points() }
460}
461
462pub fn begin_line() {
464 unsafe { Fl_begin_line() }
465}
466
467pub fn begin_loop() {
469 unsafe { Fl_begin_loop() }
470}
471
472pub fn begin_polygon() {
474 unsafe { Fl_begin_polygon() }
475}
476
477pub fn vertex(x: f64, y: f64) {
479 unsafe { Fl_vertex(x, y) }
480}
481
482pub fn end_points() {
484 unsafe { Fl_end_points() }
485}
486
487pub fn end_line() {
489 unsafe { Fl_end_line() }
490}
491
492pub fn end_loop() {
494 unsafe { Fl_end_loop() }
495}
496
497pub fn end_polygon() {
499 unsafe { Fl_end_polygon() }
500}
501
502pub fn begin_complex_polygon() {
504 unsafe { Fl_begin_complex_polygon() }
505}
506
507pub fn gap() {
509 unsafe { Fl_gap() }
510}
511
512pub fn end_complex_polygon() {
514 unsafe { Fl_end_complex_polygon() }
515}
516
517pub fn set_font(face: Font, fsize: i32) {
519 unsafe { Fl_set_draw_font(face.bits(), fsize) }
520}
521
522pub fn font() -> Font {
524 unsafe { mem::transmute(Fl_font()) }
525}
526
527pub fn size() -> i32 {
529 unsafe { Fl_size() }
530}
531
532pub fn height() -> i32 {
534 unsafe { Fl_height() }
535}
536
537pub fn set_height(font: Font, size: i32) {
539 unsafe {
540 Fl_set_height(font.bits(), size);
541 }
542}
543
544pub fn descent() -> i32 {
547 unsafe { Fl_descent() }
548}
549
550pub fn width(txt: &str) -> f64 {
552 let txt = CString::safe_new(txt);
553 unsafe { Fl_width(txt.as_ptr()) }
554}
555
556pub fn width2(txt: &str, n: i32) -> f64 {
558 let txt = CString::safe_new(txt);
559 unsafe { Fl_width2(txt.as_ptr(), n) }
560}
561
562pub fn measure(txt: &str, draw_symbols: bool) -> (i32, i32) {
564 let txt = CString::safe_new(txt);
565 let (mut x, mut y) = (0, 0);
566 unsafe {
567 Fl_measure(txt.as_ptr(), &mut x, &mut y, draw_symbols as i32);
568 }
569 (x, y)
570}
571
572pub fn wrap_measure(txt: &str, width: i32, draw_symbols: bool) -> (i32, i32) {
576 let txt = CString::safe_new(txt);
577 let (mut x, mut y) = (width, 0);
578 unsafe {
579 Fl_measure(txt.as_ptr(), &mut x, &mut y, draw_symbols as i32);
580 }
581 (x, y)
582}
583
584pub fn text_extents(txt: &str) -> (i32, i32, i32, i32) {
587 let txt = CString::safe_new(txt);
588 let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
589 unsafe {
590 Fl_text_extents(txt.as_ptr(), &mut x, &mut y, &mut w, &mut h);
591 }
592 (x, y, w, h)
593}
594
595pub fn char_width(c: char) -> f64 {
597 unsafe { Fl_width3(c as u32) }
598}
599
600pub fn latin1_to_local(txt: &str, n: i32) -> String {
602 let txt = CString::safe_new(txt);
603 unsafe {
604 let x = Fl_latin1_to_local(txt.as_ptr(), n);
605 assert!(!x.is_null());
606 CStr::from_ptr(x as *mut raw::c_char)
607 .to_string_lossy()
608 .to_string()
609 }
610}
611
612pub fn local_to_latin1(txt: &str, n: i32) -> String {
614 let txt = CString::safe_new(txt);
615 unsafe {
616 let x = Fl_local_to_latin1(txt.as_ptr(), n);
617 assert!(!x.is_null());
618 CStr::from_ptr(x as *mut raw::c_char)
619 .to_string_lossy()
620 .to_string()
621 }
622}
623
624pub fn draw_text(txt: &str, x: i32, y: i32) {
626 if size() == -1 && txt.len() == 1 {
627 return;
628 }
629 let txt = CString::safe_new(txt);
630 unsafe { Fl_draw(txt.as_ptr(), x, y) }
631}
632
633pub fn draw_text2(string: &str, x: i32, y: i32, width: i32, height: i32, align: Align) {
635 if size() == -1 && string.len() == 1 {
636 return;
637 }
638 let s = CString::safe_new(string);
639 unsafe { Fl_draw_text2(s.as_ptr(), x, y, width, height, align.bits()) }
640}
641
642pub fn draw_text_angled(angle: i32, txt: &str, x: i32, y: i32) {
644 if size() == -1 && txt.len() == 1 {
645 return;
646 }
647 let txt = CString::safe_new(txt);
648 unsafe { Fl_draw2(angle, txt.as_ptr(), x, y) }
649}
650
651pub fn rtl_draw(txt: &str, x: i32, y: i32) {
653 if size() == -1 && txt.len() == 1 {
654 return;
655 }
656 let len = txt.len() as i32;
657 let txt = CString::safe_new(txt);
658 unsafe { Fl_rtl_draw(txt.as_ptr(), len, x, y) }
659}
660
661pub fn draw_frame(string: &str, x: i32, y: i32, width: i32, height: i32) {
667 assert!(string.len() % 4 == 0);
668 let s = CString::safe_new(string);
669 unsafe { Fl_frame(s.as_ptr(), x, y, width, height) }
670}
671
672pub fn draw_frame2(string: &str, x: i32, y: i32, width: i32, height: i32) {
676 assert!(string.len() % 4 == 0);
677 let s = CString::safe_new(string);
678 unsafe { Fl_frame2(s.as_ptr(), x, y, width, height) }
679}
680
681pub fn draw_box(box_type: FrameType, x: i32, y: i32, w: i32, h: i32, color: Color) {
683 unsafe { Fl_draw_box(box_type.as_i32(), x, y, w, h, color.bits()) }
684}
685
686pub fn can_do_alpha_blending() -> bool {
688 unsafe { Fl_can_do_alpha_blending() != 0 }
689}
690
691pub fn shortcut_label(shortcut: Shortcut) -> String {
693 unsafe {
694 let x = Fl_shortcut_label(shortcut.bits() as u32);
695 assert!(!x.is_null());
696 CStr::from_ptr(x as *mut raw::c_char)
697 .to_string_lossy()
698 .to_string()
699 }
700}
701
702pub fn overlay_rect(x: i32, y: i32, w: i32, h: i32) {
704 unsafe { Fl_overlay_rect(x, y, w, h) }
705}
706
707pub fn overlay_clear() {
709 unsafe { Fl_overlay_clear() }
710}
711
712pub fn set_cursor(cursor: Cursor) {
714 unsafe { Fl_set_cursor(cursor as i32) }
715}
716
717pub fn set_cursor_with_color(cursor: Cursor, fg: Color, bg: Color) {
719 unsafe { Fl_set_cursor2(cursor as i32, fg.bits() as i32, bg.bits() as i32) }
720}
721
722pub fn set_status(x: i32, y: i32, w: i32, h: i32) {
724 unsafe { Fl_set_status(x, y, w, h) }
725}
726
727pub fn set_spot<Win: WindowExt>(font: Font, size: i32, x: i32, y: i32, w: i32, h: i32, win: &Win) {
729 unsafe {
730 Fl_set_spot(
731 font.bits(),
732 size,
733 x,
734 y,
735 w,
736 h,
737 win.as_widget_ptr() as *mut raw::c_void,
738 )
739 }
740}
741
742pub fn reset_spot() {
744 unsafe { Fl_reset_spot() }
745}
746
747pub fn capture_window<Win: WindowExt>(win: &mut Win) -> Result<RgbImage, FltkError> {
759 let cp = win.width() * win.height() * 3;
760 win.show();
761 unsafe {
762 let x = Fl_read_image(std::ptr::null_mut(), 0, 0, win.width(), win.height(), 0);
763 if x.is_null() {
764 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
765 } else {
766 let x = std::slice::from_raw_parts(x, cp as usize);
767 Ok(RgbImage::new(
768 x,
769 win.width(),
770 win.height(),
771 ColorDepth::Rgb8,
772 )?)
773 }
774 }
775}
776
777pub fn capture_window_part<Win: WindowExt>(
789 win: &mut Win,
790 x: i32,
791 y: i32,
792 w: i32,
793 h: i32,
794) -> Result<RgbImage, FltkError> {
795 let cp = win.width() * win.height() * 3;
796 win.show();
797 unsafe {
798 let x = Fl_capture_window_part(win.as_widget_ptr() as _, x, y, w, h);
799 if x.is_null() {
800 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
801 } else {
802 let x = std::slice::from_raw_parts(x, cp as usize);
803 Ok(RgbImage::new(x, w, h, ColorDepth::Rgb8)?)
804 }
805 }
806}
807
808pub fn capture_offscreen(offs: &mut Offscreen, w: i32, h: i32) -> Result<RgbImage, FltkError> {
820 let cp = w * h * 3;
821 unsafe {
822 offs.begin();
823 let x = Fl_read_image(std::ptr::null_mut(), 0, 0, w, h, 0);
824 offs.end();
825 if x.is_null() {
826 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
827 } else {
828 let x = std::slice::from_raw_parts(x, cp as usize);
829 Ok(RgbImage::new(x, w, h, ColorDepth::Rgb8)?)
830 }
831 }
832}
833
834pub fn capture_surface(surface: &ImageSurface, w: i32, h: i32) -> Result<RgbImage, FltkError> {
846 let cp = w * h * 3;
847 unsafe {
848 ImageSurface::push_current(surface);
849 let x = Fl_read_image(std::ptr::null_mut(), 0, 0, w, h, 0);
850 ImageSurface::pop_current();
851 if x.is_null() {
852 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
853 } else {
854 let x = std::slice::from_raw_parts(x, cp as usize);
855 Ok(RgbImage::new(x, w, h, ColorDepth::Rgb8)?)
856 }
857 }
858}
859
860pub fn draw_rgba<'a, T: WidgetBase>(wid: &'a mut T, fb: &'a [u8]) -> Result<(), FltkError> {
864 let width = wid.width();
865 let height = wid.height();
866 let mut img = crate::image::RgbImage::new(fb, width, height, ColorDepth::Rgba8)?;
867 wid.draw(move |s| {
868 let x = s.x();
869 let y = s.y();
870 let w = s.width();
871 let h = s.height();
872 img.scale(w, h, false, true);
873 img.draw(x, y, w, h);
874 });
875 Ok(())
876}
877
878pub unsafe fn draw_rgba_nocopy<T: WidgetBase>(wid: &mut T, fb: &[u8]) {
882 let ptr = fb.as_ptr();
883 let len = fb.len();
884 let width = wid.width();
885 let height = wid.height();
886 wid.draw(move |s| {
887 let x = s.x();
888 let y = s.y();
889 let w = s.width();
890 let h = s.height();
891 if let Ok(mut img) = crate::image::RgbImage::from_data(
892 std::slice::from_raw_parts(ptr, len),
893 width,
894 height,
895 ColorDepth::Rgba8,
896 ) {
897 img.scale(w, h, false, true);
898 img.draw(x, y, w, h);
899 }
900 });
901}
902
903pub fn draw_rgb<'a, T: WidgetBase>(wid: &'a mut T, fb: &'a [u8]) -> Result<(), FltkError> {
907 let width = wid.width();
908 let height = wid.height();
909 let mut img = crate::image::RgbImage::new(fb, width, height, ColorDepth::Rgb8)?;
910 wid.draw(move |s| {
911 let x = s.x();
912 let y = s.y();
913 let w = s.width();
914 let h = s.height();
915 img.scale(w, h, false, true);
916 img.draw(x, y, w, h);
917 });
918 Ok(())
919}
920
921pub unsafe fn draw_rgb_nocopy<T: WidgetBase>(wid: &mut T, fb: &[u8]) {
925 let ptr = fb.as_ptr();
926 let len = fb.len();
927 let width = wid.width();
928 let height = wid.height();
929 wid.draw(move |s| {
930 let x = s.x();
931 let y = s.y();
932 let w = s.width();
933 let h = s.height();
934 if let Ok(mut img) = crate::image::RgbImage::from_data(
935 std::slice::from_raw_parts(ptr, len),
936 width,
937 height,
938 ColorDepth::Rgb8,
939 ) {
940 img.scale(w, h, false, true);
941 img.draw(x, y, w, h);
942 }
943 });
944}
945
946pub fn draw_image(
952 data: &[u8],
953 x: i32,
954 y: i32,
955 w: i32,
956 h: i32,
957 depth: ColorDepth,
958) -> Result<(), FltkError> {
959 let sz = (w * h * depth as i32) as usize;
960 if sz > data.len() {
961 return Err(FltkError::Internal(FltkErrorKind::ImageFormatError));
962 }
963 unsafe {
964 Fl_draw_image(data.as_ptr(), x, y, w, h, depth as i32, 0);
965 }
966 Ok(())
967}
968
969pub fn draw_check(x: i32, y: i32, w: i32, h: i32, col: Color) {
971 unsafe {
972 Fl_draw_check(x, y, w, h, col.bits());
973 }
974}
975
976pub unsafe fn draw_image2(data: &[u8], x: i32, y: i32, w: i32, h: i32, depth: i32, line_data: i32) {
986 Fl_draw_image(data.as_ptr(), x, y, w, h, depth, line_data);
987}
988
989pub fn draw_rbox(x: i32, y: i32, w: i32, h: i32, max_radius: i32, fill: bool, col: Color) {
991 let max_radius = if max_radius < 0 { 0 } else { max_radius };
992 let offset: [f64; 5] = [0.0, 0.07612, 0.29289, 0.61732, 1.0];
993 let mut rs = w * 2 / 5;
994 let rsy = h * 2 / 5;
995 if rs > rsy {
996 rs = rsy;
997 }
998 if rs > max_radius {
999 rs = max_radius;
1000 }
1001 if rs == 5 {
1002 rs = 4;
1003 }
1004 if rs == 7 {
1005 rs = 8;
1006 }
1007
1008 let rs = rs as f64;
1009 let x = x as f64;
1010 let y = y as f64;
1011 let w = w as f64;
1012 let h = h as f64;
1013 let old_col = get_color();
1014 let len = offset.len();
1015
1016 set_draw_color(col);
1017 if fill {
1018 begin_polygon();
1019 } else {
1020 begin_loop();
1021 }
1022 unsafe {
1023 for i in 0..len {
1024 vertex(
1025 0.5 + x + offset.get_unchecked(len - i - 1) * rs,
1026 0.5 + y + offset.get_unchecked(i) * rs,
1027 );
1028 }
1029 for i in 0..len {
1030 vertex(
1031 0.5 + x + offset.get_unchecked(i) * rs,
1032 0.5 + y + h - 1.0 - offset.get_unchecked(len - i - 1) * rs,
1033 );
1034 }
1035 for i in 0..len {
1036 vertex(
1037 0.5 + x + w - 1.0 - offset.get_unchecked(len - i - 1) * rs,
1038 0.5 + y + h - 1.0 - offset.get_unchecked(i) * rs,
1039 );
1040 }
1041 for i in 0..len {
1042 vertex(
1043 0.5 + x + w - 1.0 - offset.get_unchecked(i) * rs,
1044 0.5 + y + offset.get_unchecked(len - i - 1) * rs,
1045 );
1046 }
1047 }
1048 if fill {
1049 end_polygon();
1050 } else {
1051 end_loop();
1052 }
1053 set_draw_color(old_col);
1054}
1055
1056#[cfg(feature = "enable-glwindow")]
1057pub unsafe fn gl_start() {
1061 fltk_sys::window::Fl_gl_start();
1062}
1063
1064#[cfg(feature = "enable-glwindow")]
1065pub unsafe fn gl_finish() {
1069 fltk_sys::window::Fl_gl_finish();
1070}
1071
1072pub fn draw_rounded_rect(x: i32, y: i32, w: i32, h: i32, r: i32) {
1074 unsafe { Fl_rounded_rect(x, y, w, h, r) }
1075}
1076
1077pub fn draw_rounded_rectf(x: i32, y: i32, w: i32, h: i32, r: i32) {
1079 unsafe { Fl_rounded_rectf(x, y, w, h, r) }
1080}
1081
1082pub fn draw_circle_fill(x: i32, y: i32, d: i32, c: Color) {
1084 unsafe {
1085 Fl_draw_circle(x, y, d, c.bits());
1086 }
1087}
1088
1089pub fn draw_text_n(string: &str, x: i32, y: i32) {
1091 let len = string.len();
1092 if size() == -1 && len == 1 {
1093 return;
1094 }
1095 unsafe { Fl_draw3(string.as_ptr() as _, len as _, x, y) }
1096}
1097
1098pub fn override_scale() -> f32 {
1100 unsafe { Fl_override_scale() }
1101}
1102
1103pub fn restore_scale(s: f32) {
1105 unsafe { Fl_restore_scale(s) }
1106}