mirror of
https://gitlab.com/cleanflash/installer.git
synced 2026-08-13 10:51:37 +08:00
Remove PNG loading
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::Rect;
|
||||
use crate::renderer::{Renderer, RgbaImage};
|
||||
use crate::renderer::Renderer;
|
||||
|
||||
/// An image-based checkbox matching the C# ImageCheckBox control.
|
||||
/// A software-rendered checkbox with a gray gradient, black outline, and white checkmark.
|
||||
pub struct ImageCheckBox {
|
||||
pub rect: Rect,
|
||||
pub checked: bool,
|
||||
@@ -32,59 +32,34 @@ impl ImageCheckBox {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
checked_img: &RgbaImage,
|
||||
unchecked_img: &RgbaImage,
|
||||
) {
|
||||
pub fn draw(&self, renderer: &mut Renderer) {
|
||||
if !self.visible {
|
||||
return;
|
||||
}
|
||||
let img = if self.checked {
|
||||
checked_img
|
||||
} else {
|
||||
unchecked_img
|
||||
};
|
||||
if img.width > 0 && img.height > 0 {
|
||||
renderer.draw_image_scaled(self.rect.x, self.rect.y, self.rect.w, self.rect.h, img);
|
||||
} else {
|
||||
// Fallback: draw a simple square.
|
||||
let bg = if self.checked {
|
||||
Renderer::rgb(97, 147, 232)
|
||||
} else {
|
||||
Renderer::rgb(80, 80, 80)
|
||||
};
|
||||
renderer.fill_rect(self.rect.x, self.rect.y, self.rect.w, self.rect.h, bg);
|
||||
renderer.draw_rect(
|
||||
self.rect.x,
|
||||
self.rect.y,
|
||||
self.rect.w,
|
||||
self.rect.h,
|
||||
Renderer::rgb(160, 160, 160),
|
||||
);
|
||||
if self.checked {
|
||||
// Draw a simple checkmark.
|
||||
let cx = self.rect.x + 5;
|
||||
let cy = self.rect.y + 10;
|
||||
for i in 0..4 {
|
||||
renderer.set_pixel(cx + i, cy + i, Renderer::rgb(255, 255, 255));
|
||||
renderer.set_pixel(cx + i, cy + i + 1, Renderer::rgb(255, 255, 255));
|
||||
}
|
||||
for i in 0..8 {
|
||||
renderer.set_pixel(cx + 3 + i, cy + 3 - i, Renderer::rgb(255, 255, 255));
|
||||
renderer.set_pixel(cx + 3 + i, cy + 4 - i, Renderer::rgb(255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
let r = self.rect;
|
||||
|
||||
// Gray gradient background (matching button style).
|
||||
let color1 = Renderer::rgb(118, 118, 118);
|
||||
let color2 = Renderer::rgb(81, 81, 81);
|
||||
renderer.fill_gradient_v(r.x, r.y, r.w, r.h, color1, color2);
|
||||
|
||||
// Black 1px outline.
|
||||
renderer.draw_rect(r.x, r.y, r.w, r.h, Renderer::rgb(0, 0, 0));
|
||||
|
||||
// White checkmark when checked.
|
||||
if self.checked {
|
||||
let white = Renderer::rgb(255, 255, 255);
|
||||
Self::draw_checkmark(renderer, r.x, r.y, r.w, r.h, white);
|
||||
}
|
||||
|
||||
if !self.enabled {
|
||||
// Dim overlay.
|
||||
for dy in 0..self.rect.h {
|
||||
for dx in 0..self.rect.w {
|
||||
for dy in 0..r.h {
|
||||
for dx in 0..r.w {
|
||||
renderer.blend_pixel(
|
||||
self.rect.x + dx,
|
||||
self.rect.y + dy,
|
||||
r.x + dx,
|
||||
r.y + dy,
|
||||
Renderer::rgb(50, 51, 51),
|
||||
100,
|
||||
);
|
||||
@@ -92,4 +67,72 @@ impl ImageCheckBox {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a checkmark scaled to fit within the given box.
|
||||
fn draw_checkmark(renderer: &mut Renderer, bx: i32, by: i32, bw: i32, bh: i32, color: u32) {
|
||||
// Checkmark geometry defined in a normalised coordinate space.
|
||||
// The check goes from bottom-left, down to a valley, then up to top-right.
|
||||
// Key points (in fractions of size):
|
||||
// start: (0.20, 0.50)
|
||||
// valley: (0.40, 0.72)
|
||||
// end: (0.80, 0.25)
|
||||
// We draw two thick line segments between these points.
|
||||
|
||||
let w = bw as f32;
|
||||
let h = bh as f32;
|
||||
|
||||
// Absolute coordinates of the three key points.
|
||||
let x0 = bx as f32 + w * 0.20;
|
||||
let y0 = by as f32 + h * 0.48;
|
||||
let x1 = bx as f32 + w * 0.40;
|
||||
let y1 = by as f32 + h * 0.72;
|
||||
let x2 = bx as f32 + w * 0.80;
|
||||
let y2 = by as f32 + h * 0.25;
|
||||
|
||||
// Line thickness scales with checkbox size.
|
||||
let thickness = (w * 0.14).max(1.5);
|
||||
|
||||
draw_thick_line(renderer, x0, y0, x1, y1, thickness, color);
|
||||
draw_thick_line(renderer, x1, y1, x2, y2, thickness, color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a thick line between two points using filled circles along the path (round caps).
|
||||
fn draw_thick_line(
|
||||
renderer: &mut Renderer,
|
||||
x0: f32,
|
||||
y0: f32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
thickness: f32,
|
||||
color: u32,
|
||||
) {
|
||||
let dx = x1 - x0;
|
||||
let dy = y1 - y0;
|
||||
let dist = (dx * dx + dy * dy).sqrt();
|
||||
let steps = (dist * 2.0).ceil() as i32;
|
||||
let half = thickness / 2.0;
|
||||
|
||||
for i in 0..=steps {
|
||||
let t = i as f32 / steps.max(1) as f32;
|
||||
let cx = x0 + dx * t;
|
||||
let cy = y0 + dy * t;
|
||||
|
||||
// Fill a small circle at (cx, cy).
|
||||
let min_x = (cx - half).floor() as i32;
|
||||
let max_x = (cx + half).ceil() as i32;
|
||||
let min_y = (cy - half).floor() as i32;
|
||||
let max_y = (cy + half).ceil() as i32;
|
||||
let r_sq = half * half;
|
||||
|
||||
for py in min_y..=max_y {
|
||||
for px in min_x..=max_x {
|
||||
let fdx = px as f32 + 0.5 - cx;
|
||||
let fdy = py as f32 + 0.5 - cy;
|
||||
if fdx * fdx + fdy * fdy <= r_sq {
|
||||
renderer.set_pixel(px, py, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user