wallpaper_app/drawing/
primitives.rs

1use std::ptr::null_mut;
2
3use winapi::um::wingdi::{
4    SelectObject,
5    DeleteObject,
6    CreateSolidBrush,
7    CreatePen,
8    MoveToEx,
9    LineTo, CreateCompatibleDC, CreateCompatibleBitmap, BitBlt, SRCCOPY, DeleteDC, Ellipse,
10};
11
12use winapi::um::wingdi::PS_SOLID;
13
14use winapi::um::winuser::{
15    PAINTSTRUCT,
16    FillRect,
17};
18
19use winapi::shared::windef::{
20    HDC,
21    COLORREF, HBITMAP, RECT, HBRUSH, HPEN, HGDIOBJ,
22};
23
24pub struct DrawFrameData {
25    pub hdc: HDC,
26    h_bmp_mem: HBITMAP,
27    h_old_bmp_mem: HBITMAP,
28}
29
30pub struct SolidPenData {
31    hdc: HDC,
32    pen: HPEN,
33    old_pen: HGDIOBJ,
34}
35
36/// Return (brush, old_brush)
37pub fn change_solid_brush(hdc: HDC, color: u32) -> (HBRUSH, HBRUSH) {
38    let brush: HBRUSH = unsafe { CreateSolidBrush(color) };
39    let old_brush = unsafe { SelectObject(hdc, brush as _) } as HBRUSH;
40    (brush, old_brush)
41}
42
43pub fn revert_brush(hdc: HDC, brush: HBRUSH, old_brush: HBRUSH) {
44    unsafe {
45        SelectObject(hdc, old_brush as _);
46        DeleteObject(brush as _);
47    }
48}
49
50pub fn open_draw_frame(hdc: HDC, width: i32, height: i32) -> DrawFrameData {
51    unsafe {
52        let h_mem_dc = CreateCompatibleDC(hdc);
53        let h_bmp_mem = CreateCompatibleBitmap(hdc, width, height);
54        let h_old_bmp_mem = SelectObject(h_mem_dc, h_bmp_mem as _) as HBITMAP;
55
56        DrawFrameData { hdc: h_mem_dc, h_bmp_mem, h_old_bmp_mem }
57    }
58}
59
60pub fn close_draw_frame(hdc: HDC, width: i32, height: i32, draw_frame_data: DrawFrameData) {
61    unsafe {
62        BitBlt(hdc, 0, 0, width, height, draw_frame_data.hdc, 0, 0, SRCCOPY);
63
64        SelectObject(draw_frame_data.hdc, draw_frame_data.h_old_bmp_mem as _);
65        DeleteObject(draw_frame_data.h_bmp_mem as _);
66        DeleteDC(draw_frame_data.hdc);
67    }
68}
69
70pub fn create_solid_pen(hdc: HDC, color: COLORREF) -> SolidPenData {
71    let pen = unsafe { CreatePen(PS_SOLID as i32, 2, color) };
72    let old_pen = unsafe { SelectObject(hdc, pen as _) };
73    SolidPenData {
74        hdc,
75        pen,
76        old_pen,
77    }
78}
79
80pub fn draw_line(hdc: HDC, from: (i32, i32), to: (i32, i32)) {
81    unsafe { MoveToEx(hdc, from.0, from.1, null_mut()) };
82    unsafe { LineTo(hdc, to.0, to.1) };
83}
84
85pub fn close_draw_lines(data: SolidPenData) {
86    unsafe { SelectObject(data.hdc, data.old_pen) };
87    unsafe { DeleteObject(data.pen as _) };
88}
89
90/// Use current selected brush
91pub fn draw_circle(hdc: HDC, x: i32, y: i32, radius: i32) {
92    let left = x - radius;
93    let top = y - radius;
94    let right = x + radius;
95    let bottom = y + radius;
96
97    let rect = RECT {
98        left,
99        top,
100        right,
101        bottom,
102    };
103
104    unsafe {
105        Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom);
106    }
107}
108
109pub fn draw_fullscreen_rect(hdc: HDC, ps: &PAINTSTRUCT, color: COLORREF) {
110    let rect = &ps.rcPaint;
111    unsafe {
112        let brush = CreateSolidBrush(color);
113        FillRect(hdc, rect, brush);
114        DeleteObject(brush as _);
115    }
116}
117
118pub fn draw_spiral(hdc: HDC) {
119    let mut angle = 0.0f32;
120    let radius_mul = 10.0f32;
121    let start_x : f32 = 1920.0 / 2.0;
122    let start_y : f32 = 1080.0 / 2.0;
123
124    let white_color = 0xFFFFFF;
125
126    let brush: HBRUSH = unsafe { CreateSolidBrush(white_color) };
127    let old_brush = unsafe { SelectObject(hdc, brush as _) };
128
129    for i in 0..1000 {
130        // Compute radius based on angle
131        let radius = angle.powf(0.8);
132
133        // Convert polar coordinates to Cartesian coordinates
134        let x = start_x + radius * angle.cos() * radius_mul;
135        let y = start_y + radius * angle.sin() * radius_mul;
136        draw_circle(hdc, x as i32, y as i32, 3);
137
138        // Increment the angle for the next iteration
139        let c = ((i / 500) as f32).powf(0.4) + 1f32;
140        let p = 0.05 / c;
141        angle += p;
142    }
143
144    unsafe {
145        SelectObject(hdc, old_brush);
146        winapi::um::wingdi::DeleteObject(brush as _);
147    }
148
149    // ToDo: Add custom parameters!
150}