use crate::image::RgbImage;
pub use crate::prelude::*;
use fltk_sys::draw::*;
use std::ffi::{CStr, CString};
use std::mem;
use std::os::raw;
#[repr(i32)]
#[derive(WidgetType, Debug, Copy, Clone, PartialEq)]
pub enum LineStyle {
Solid = 0,
Dash,
Dot,
DashDot,
DashDotDot,
CapFlat = 100,
CapRound = 200,
CapSquare = 300,
JoinMiter = 1000,
JoinRound = 2000,
JoinBevel = 3000,
}
impl std::ops::BitOr<LineStyle> for LineStyle {
type Output = LineStyle;
fn bitor(self, rhs: LineStyle) -> Self::Output {
unsafe { std::mem::transmute(self as i32 | rhs as i32) }
}
}
pub type Region = *mut raw::c_void;
#[derive(Debug)]
pub struct Offscreen {
_inner: *mut raw::c_void,
}
unsafe impl Sync for Offscreen {}
unsafe impl Send for Offscreen {}
impl Offscreen {
pub fn new(w: i32, h: i32) -> Option<Offscreen> {
unsafe {
let x = Fl_create_offscreen(w, h);
if x.is_null() {
None
} else {
Some(Offscreen { _inner: x })
}
}
}
pub unsafe fn uninit() -> Offscreen {
Offscreen {
_inner: std::ptr::null_mut(),
}
}
pub fn begin(&self) {
assert!(!self._inner.is_null());
unsafe { Fl_begin_offscreen(self._inner) }
}
pub fn end(&self) {
assert!(!self._inner.is_null());
unsafe { Fl_end_offscreen() }
}
pub fn copy(&self, x: i32, y: i32, w: i32, h: i32, srcx: i32, srcy: i32) {
assert!(!self._inner.is_null());
unsafe { Fl_copy_offscreen(x, y, w, h, self._inner, srcx, srcy) }
}
pub fn rescale(&mut self) {
assert!(!self._inner.is_null());
unsafe { Fl_rescale_offscreen(self._inner) }
}
pub fn is_valid(&self) -> bool {
assert!(!self._inner.is_null());
!self._inner.is_null()
}
pub unsafe fn memcpy(&self) -> Offscreen {
assert!(!self._inner.is_null());
Offscreen {
_inner: self._inner,
}
}
}
impl Drop for Offscreen {
fn drop(&mut self) {
unsafe { Fl_delete_offscreen(self._inner) }
}
}
pub fn show_colormap(old_color: Color) -> Color {
unsafe { mem::transmute(Fl_show_colormap(old_color as u32)) }
}
pub fn set_color_rgb(r: u8, g: u8, b: u8) {
unsafe { Fl_set_color_rgb(r, g, b) }
}
pub fn get_color() -> Color {
unsafe { mem::transmute(Fl_get_color()) }
}
pub fn draw_line(x1: i32, y1: i32, x2: i32, y2: i32) {
unsafe {
Fl_line(x1, y1, x2, y2);
}
}
pub fn draw_point(x: i32, y: i32) {
unsafe { Fl_point(x, y) }
}
pub fn draw_rect(x: i32, y: i32, w: i32, h: i32) {
unsafe { Fl_rect(x, y, w, h) }
}
pub fn draw_rect_with_color(x: i32, y: i32, w: i32, h: i32, color: Color) {
unsafe { Fl_rect_with_color(x, y, w, h, color as u32) }
}
pub fn draw_loop(x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
unsafe {
Fl_loop(x1, y1, x2, y2, x3, y3);
}
}
pub fn draw_rect_fill(x: i32, y: i32, w: i32, h: i32, color: Color) {
unsafe { Fl_rectf_with_color(x, y, w, h, color as u32) }
}
pub fn draw_focus_rect(x: i32, y: i32, w: i32, h: i32) {
unsafe { Fl_focus_rect(x, y, w, h) }
}
pub fn set_draw_color(color: Color) {
unsafe { Fl_set_color_int(color.to_u32()) }
}
pub fn draw_circle(x: f64, y: f64, r: f64) {
unsafe {
Fl_circle(x, y, r);
}
}
pub fn draw_arc(x: i32, y: i32, width: i32, height: i32, a: f64, b: f64) {
unsafe {
Fl_arc(x, y, width, height, a, b);
}
}
pub fn draw_pie(x: i32, y: i32, width: i32, height: i32, a: f64, b: f64) {
unsafe {
Fl_pie(x, y, width, height, a, b);
}
}
pub fn set_line_style(style: LineStyle, width: i32) {
unsafe {
Fl_line_style(
style as i32,
width,
std::ptr::null_mut() as *mut std::os::raw::c_char,
);
}
}
pub fn push_clip(x: i32, y: i32, w: i32, h: i32) {
unsafe {
Fl_push_clip(x, y, w, h);
}
}
pub fn pop_clip() {
unsafe {
Fl_pop_clip();
}
}
pub fn set_clip_region(r: Region) {
assert!(!r.is_null());
unsafe { Fl_set_clip_region(r) }
}
pub fn clip_region() -> Region {
unsafe {
let ptr = Fl_clip_region();
assert!(!ptr.is_null());
ptr
}
}
pub fn push_no_clip() {
unsafe { Fl_push_no_clip() }
}
pub fn not_clipped(x: i32, y: i32, w: i32, h: i32) -> bool {
unsafe {
match Fl_not_clipped(x, y, w, h) {
0 => false,
_ => true,
}
}
}
pub fn restore_clip() {
unsafe { Fl_restore_clip() }
}
#[allow(dead_code)]
fn copy_offscreen(x: i32, y: i32, w: i32, h: i32, pixmap: &Offscreen, srcx: i32, srcy: i32) {
unsafe { Fl_copy_offscreen(x, y, w, h, pixmap._inner, srcx, srcy) }
}
pub fn create_offscreen(w: i32, h: i32) -> Offscreen {
unsafe {
let x = Fl_create_offscreen(w, h);
assert!(!x.is_null());
Offscreen { _inner: x }
}
}
#[allow(dead_code)]
fn begin_offscreen(b: &Offscreen) {
unsafe { Fl_begin_offscreen(b._inner) }
}
pub fn end_offscreen() {
unsafe { Fl_end_offscreen() }
}
#[allow(dead_code)]
fn delete_offscreen(bitmap: &mut Offscreen) {
unsafe { Fl_delete_offscreen(bitmap._inner) }
}
#[allow(dead_code)]
fn rescale_offscreen(ctx: &mut Offscreen) {
unsafe { Fl_rescale_offscreen(ctx._inner) }
}
pub fn transform_x(x: f64, y: f64) -> f64 {
unsafe { Fl_transform_x(x, y) }
}
pub fn transform_y(x: f64, y: f64) -> f64 {
unsafe { Fl_transform_y(x, y) }
}
pub fn transform_dx(x: f64, y: f64) -> f64 {
unsafe { Fl_transform_dx(x, y) }
}
pub fn transform_dy(x: f64, y: f64) -> f64 {
unsafe { Fl_transform_dy(x, y) }
}
pub fn transformed_vertex(xf: f64, yf: f64) {
unsafe { Fl_transformed_vertex(xf, yf) }
}
pub fn draw_rectf(x: i32, y: i32, w: i32, h: i32) {
unsafe { Fl_rectf(x, y, w, h) }
}
pub fn draw_rectf_with_rgb(
x: i32,
y: i32,
width: i32,
height: i32,
color_r: u8,
color_g: u8,
color_b: u8,
) {
unsafe { Fl_rectf_with_rgb(x, y, width, height, color_r, color_g, color_b) }
}
pub fn draw_line2(x: i32, y: i32, x1: i32, y1: i32, x2: i32, y2: i32) {
unsafe { Fl_line2(x, y, x1, y1, x2, y2) }
}
pub fn draw_loop2(x: i32, y: i32, x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
unsafe { Fl_loop2(x, y, x1, y1, x2, y2, x3, y3) }
}
pub fn draw_polygon(x: i32, y: i32, x1: i32, y1: i32, x2: i32, y2: i32) {
unsafe { Fl_polygon(x, y, x1, y1, x2, y2) }
}
pub fn draw_polygon2(x: i32, y: i32, x1: i32, y1: i32, x2: i32, y2: i32, x3: i32, y3: i32) {
unsafe { Fl_polygon2(x, y, x1, y1, x2, y2, x3, y3) }
}
pub fn draw_curve(x0: f64, y0: f64, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) {
unsafe { Fl_curve(x0, y0, x1, y1, x2, y2, x3, y3) }
}
pub fn draw_arc2(x: f64, y: f64, r: f64, start: f64, end: f64) {
unsafe { Fl_arc2(x, y, r, start, end) }
}
pub fn draw_xyline(x: i32, y: i32, x1: i32) {
unsafe { Fl_xyline(x, y, x1) }
}
pub fn draw_xyline2(x: i32, y: i32, x1: i32, y2: i32) {
unsafe { Fl_xyline2(x, y, x1, y2) }
}
pub fn draw_xyline3(x: i32, y: i32, x1: i32, y2: i32, x3: i32) {
unsafe { Fl_xyline3(x, y, x1, y2, x3) }
}
pub fn draw_yxline(x: i32, y: i32, y1: i32) {
unsafe { Fl_yxline(x, y, y1) }
}
pub fn draw_yxline2(x: i32, y: i32, y1: i32, x2: i32) {
unsafe { Fl_yxline2(x, y, y1, x2) }
}
pub fn draw_yxline3(x: i32, y: i32, y1: i32, x2: i32, y3: i32) {
unsafe { Fl_yxline3(x, y, y1, x2, y3) }
}
pub fn push_matrix() {
unsafe { Fl_push_matrix() }
}
pub fn pop_matrix() {
unsafe { Fl_pop_matrix() }
}
pub fn scale_xy(x: f64, y: f64) {
unsafe { Fl_scale(x, y) }
}
pub fn scale_x(x: f64) {
unsafe { Fl_scale2(x) }
}
pub fn translate(x: f64, y: f64) {
unsafe { Fl_translate(x, y) }
}
pub fn rotate(d: f64) {
unsafe { Fl_rotate(d) }
}
pub fn mult_matrix(val_a: f64, val_b: f64, val_c: f64, val_d: f64, x: f64, y: f64) {
unsafe { Fl_mult_matrix(val_a, val_b, val_c, val_d, x, y) }
}
pub fn begin_points() {
unsafe { Fl_begin_points() }
}
pub fn begin_line() {
unsafe { Fl_begin_line() }
}
pub fn begin_loop() {
unsafe { Fl_begin_loop() }
}
pub fn begin_polygon() {
unsafe { Fl_begin_polygon() }
}
pub fn vertex(x: f64, y: f64) {
unsafe { Fl_vertex(x, y) }
}
pub fn end_points() {
unsafe { Fl_end_points() }
}
pub fn end_line() {
unsafe { Fl_end_line() }
}
pub fn end_loop() {
unsafe { Fl_end_loop() }
}
pub fn end_polygon() {
unsafe { Fl_end_polygon() }
}
pub fn begin_complex_polygon() {
unsafe { Fl_begin_complex_polygon() }
}
pub fn gap() {
unsafe { Fl_gap() }
}
pub fn end_complex_polygon() {
unsafe { Fl_end_complex_polygon() }
}
pub fn set_font(face: Font, fsize: u32) {
unsafe { Fl_set_font(face as i32, fsize as i32) }
}
pub fn font() -> Font {
unsafe { mem::transmute(Fl_font()) }
}
pub fn size() -> u32 {
unsafe { Fl_size() as u32 }
}
pub fn height() -> i32 {
unsafe { Fl_height() }
}
pub fn set_height(font: Font, size: u32) {
unsafe {
Fl_set_height(font as i32, size as i32);
}
}
pub fn descent() -> i32 {
unsafe { Fl_descent() }
}
pub fn width(txt: &str) -> f64 {
let txt = CString::new(txt).unwrap();
unsafe { Fl_width(txt.as_ptr()) }
}
pub fn width2(txt: &str, n: i32) -> f64 {
let txt = CString::new(txt).unwrap();
unsafe { Fl_width2(txt.as_ptr(), n) }
}
pub fn char_width(c: char) -> f64 {
unsafe { Fl_width3(c as u32) }
}
pub fn latin1_to_local(txt: &str, n: i32) -> String {
let txt = CString::new(txt).unwrap();
unsafe {
let x = Fl_latin1_to_local(txt.as_ptr(), n);
assert!(!x.is_null());
CStr::from_ptr(x as *mut raw::c_char)
.to_string_lossy()
.to_string()
}
}
pub fn local_to_latin1(txt: &str, n: i32) -> String {
let txt = CString::new(txt).unwrap();
unsafe {
let x = Fl_local_to_latin1(txt.as_ptr(), n);
assert!(!x.is_null());
CStr::from_ptr(x as *mut raw::c_char)
.to_string_lossy()
.to_string()
}
}
pub fn draw_text(txt: &str, x: i32, y: i32) {
let txt = CString::new(txt).unwrap();
unsafe { Fl_draw(txt.as_ptr(), x, y) }
}
pub fn draw_text2(string: &str, x: i32, y: i32, width: i32, height: i32, align: Align) {
let s = CString::new(string).unwrap();
unsafe { Fl_draw_text2(s.as_ptr(), x, y, width, height, align as i32) }
}
pub fn draw_text_angled(angle: i32, txt: &str, x: i32, y: i32) {
let txt = CString::new(txt).unwrap();
unsafe { Fl_draw2(angle, txt.as_ptr(), x, y) }
}
pub fn rtl_draw(txt: &str, x: i32, y: i32) {
let n = txt.len() as i32;
let txt = CString::new(txt).unwrap();
unsafe { Fl_rtl_draw(txt.as_ptr(), n, x, y) }
}
pub fn draw_frame(string: &str, x: i32, y: i32, width: i32, height: i32) {
let s = CString::new(string).unwrap();
unsafe { Fl_frame(s.as_ptr(), x, y, width, height) }
}
pub fn draw_frame2(string: &str, x: i32, y: i32, width: i32, height: i32) {
let s = CString::new(string).unwrap();
unsafe { Fl_frame2(s.as_ptr(), x, y, width, height) }
}
pub fn draw_box(box_type: FrameType, x: i32, y: i32, w: i32, h: i32, color: Color) {
unsafe { Fl_draw_box(box_type as i32, x, y, w, h, color as u32) }
}
pub fn can_do_alpha_blending() -> bool {
unsafe {
match Fl_can_do_alpha_blending() {
0 => false,
_ => true,
}
}
}
pub fn shortcut_label(shortcut: Shortcut) -> String {
unsafe {
let x = Fl_shortcut_label(shortcut as u32);
assert!(!x.is_null());
CStr::from_ptr(x as *mut raw::c_char)
.to_string_lossy()
.to_string()
}
}
pub fn overlay_rect(x: i32, y: i32, w: i32, h: i32) {
unsafe { Fl_overlay_rect(x, y, w, h) }
}
pub fn overlay_clear() {
unsafe { Fl_overlay_clear() }
}
pub fn set_cursor(cursor: Cursor) {
unsafe { Fl_set_cursor(cursor as i32) }
}
pub fn set_cursor_with_color(cursor: Cursor, fg: Color, bg: Color) {
unsafe { Fl_set_cursor2(cursor as i32, fg as i32, bg as i32) }
}
pub fn set_status(x: i32, y: i32, w: i32, h: i32) {
unsafe { Fl_set_status(x, y, w, h) }
}
pub fn set_spot<Win: WindowExt>(font: Font, size: u32, x: i32, y: i32, w: i32, h: i32, win: &Win) {
unsafe {
assert!(!win.was_deleted());
Fl_set_spot(
font as i32,
size as i32,
x,
y,
w,
h,
win.as_widget_ptr() as *mut raw::c_void,
)
}
}
pub fn reset_spot() {
unsafe { Fl_reset_spot() }
}
pub fn capture_window<Win: WindowExt>(win: &mut Win) -> Result<RgbImage, FltkError> {
assert!(!win.was_deleted());
let cp = win.width() as u32 * win.height() as u32 * 3;
win.show();
unsafe {
let x = Fl_read_image(std::ptr::null_mut(), 0, 0, win.width(), win.height(), 0);
if x.is_null() {
Err(FltkError::Internal(FltkErrorKind::FailedOperation))
} else {
let x = std::slice::from_raw_parts(x, cp as usize).to_vec();
Ok(RgbImage::new(
&x,
win.width() as u32,
win.height() as u32,
3,
)?)
}
}
}
pub fn write_to_png_file<I: ImageExt>(image: &I, path: &std::path::Path) -> Result<(), FltkError> {
assert!(
std::any::type_name::<I>() != std::any::type_name::<crate::image::SvgImage>(),
"SVG images are not supported!"
);
let path = path.to_str();
if path.is_none() {
return Err(FltkError::IoError(std::io::Error::new(
std::io::ErrorKind::Other,
"Could not convert path to string!",
)));
}
let path = std::ffi::CString::new(path.unwrap())?;
unsafe {
match Fl_raw_image_to_png(
*image.to_raw_data() as *mut u8,
path.as_ptr(),
image.data_w() as i32,
image.data_h() as i32,
) {
-1 => Err(FltkError::IoError(std::io::Error::new(
std::io::ErrorKind::Other,
"Could not write image!",
))),
_ => Ok(()),
}
}
}
pub fn write_to_jpg_file<I: ImageExt>(image: &I, path: &std::path::Path) -> Result<(), FltkError> {
assert!(
std::any::type_name::<I>() != std::any::type_name::<crate::image::SvgImage>(),
"SVG images are not supported!"
);
let path = path.to_str();
if path.is_none() {
return Err(FltkError::IoError(std::io::Error::new(
std::io::ErrorKind::Other,
"Could not convert path to string!",
)));
}
let path = std::ffi::CString::new(path.unwrap())?;
unsafe {
match Fl_raw_image_to_jpg(
*image.to_raw_data() as *mut u8,
path.as_ptr(),
image.data_w() as i32,
image.data_h() as i32,
) {
-1 => Err(FltkError::IoError(std::io::Error::new(
std::io::ErrorKind::Other,
"Could not write image!",
))),
_ => Ok(()),
}
}
}
pub fn write_to_bmp_file<I: ImageExt>(image: &I, path: &std::path::Path) -> Result<(), FltkError> {
assert!(
std::any::type_name::<I>() != std::any::type_name::<crate::image::SvgImage>(),
"SVG images are not supported!"
);
let path = path.to_str();
if path.is_none() {
return Err(FltkError::IoError(std::io::Error::new(
std::io::ErrorKind::Other,
"Could not convert path to string!",
)));
}
let path = std::ffi::CString::new(path.unwrap())?;
unsafe {
match Fl_raw_image_to_bmp(
*image.to_raw_data() as *mut u8,
path.as_ptr(),
image.data_w() as i32,
image.data_h() as i32,
) {
-1 => Err(FltkError::IoError(std::io::Error::new(
std::io::ErrorKind::Other,
"Could not write image!",
))),
_ => Ok(()),
}
}
}