refactor: P0-P5 全面架构重构
P1 thiserror 类型化错误: 新增 core/src/error.rs QrError 枚举, 全链 String -> QrError, 包括 EmptyInput/InvalidVersion/DataTooLong/DecodeFail 等 8 种变体 P2 text_builder Tauri 统一: 新增 build_qr_text Tauri command, 删除前端 qrText.ts, 所有 mode 组件改为 invoke 调用 Rust 端构建文本 P3 QrConfig 颜色字段移除: 从 QrConfig/QrCode 移除 fg_color/bg_color, 改为 to_svg/to_image_bytes 参数传递 P4 前端 4 项合并: Context 拆分为 StateContext+DispatchContext (H10), 新建 useModeForm 通用 hook (M11), VCardMode grid-cols-2 网格布局 (M13), persistHistory/loadHistory 迁至 utils/storage.ts (L9) P5 算法优化: MaskedView 懒计算替代 8 次 Matrix 克隆 (H9), encoding_rs 精确 Kanji Shift JIS 映射 (H12) 验证: cargo check+clippy 通过, 81+24+7 全部测试通过
This commit is contained in:
@@ -80,8 +80,8 @@ fn fill_module(
|
||||
}
|
||||
}
|
||||
|
||||
fn overlay_logo(img: &mut RgbaImage, logo_bytes: &[u8], logo_size_pct: f32) -> Result<(), String> {
|
||||
let logo = image::load_from_memory(logo_bytes).map_err(|e| format!("Logo 加载失败: {e}"))?;
|
||||
fn overlay_logo(img: &mut RgbaImage, logo_bytes: &[u8], logo_size_pct: f32) -> Result<(), crate::error::QrError> {
|
||||
let logo = image::load_from_memory(logo_bytes).map_err(crate::error::QrError::Image)?;
|
||||
let logo = logo.to_rgba8();
|
||||
let img_w = img.width();
|
||||
let img_h = img.height();
|
||||
@@ -102,7 +102,9 @@ pub fn render_image(
|
||||
module_size: u8,
|
||||
format: OutputFormat,
|
||||
logo: Option<&[u8]>,
|
||||
) -> Result<Vec<u8>, image::ImageError> {
|
||||
fg: &[u8; 3],
|
||||
bg: &[u8; 3],
|
||||
) -> Result<Vec<u8>, crate::error::QrError> {
|
||||
let matrix_size = qr.size() as u32;
|
||||
let margin = qr.margin as u32;
|
||||
let total_size = matrix_size + 2 * margin;
|
||||
@@ -123,15 +125,7 @@ pub fn render_image(
|
||||
} else {
|
||||
false
|
||||
};
|
||||
fill_module(
|
||||
&mut img,
|
||||
x,
|
||||
y,
|
||||
module_size as u32,
|
||||
is_dark,
|
||||
&qr.fg_color,
|
||||
&qr.bg_color,
|
||||
);
|
||||
fill_module(&mut img, x, y, module_size as u32, is_dark, fg, bg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-11
@@ -1,18 +1,12 @@
|
||||
use crate::qr::QrCode;
|
||||
|
||||
pub fn render_svg(qr: &QrCode, logo: Option<&[u8]>) -> String {
|
||||
pub fn render_svg(qr: &QrCode, logo: Option<&[u8]>, fg: &[u8; 3], bg: &[u8; 3]) -> String {
|
||||
let matrix_size = qr.size() as u32;
|
||||
let margin = qr.margin as u32;
|
||||
let total = matrix_size + 2 * margin;
|
||||
|
||||
let fg = format!(
|
||||
"#{:02X}{:02X}{:02X}",
|
||||
qr.fg_color[0], qr.fg_color[1], qr.fg_color[2]
|
||||
);
|
||||
let bg = format!(
|
||||
"#{:02X}{:02X}{:02X}",
|
||||
qr.bg_color[0], qr.bg_color[1], qr.bg_color[2]
|
||||
);
|
||||
let fg_hex = format!("#{:02X}{:02X}{:02X}", fg[0], fg[1], fg[2]);
|
||||
let bg_hex = format!("#{:02X}{:02X}{:02X}", bg[0], bg[1], bg[2]);
|
||||
|
||||
let dark_count = qr
|
||||
.modules()
|
||||
@@ -25,14 +19,14 @@ pub fn render_svg(qr: &QrCode, logo: Option<&[u8]>) -> String {
|
||||
r#"<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{total}" height="{total}" viewBox="0 0 {total} {total}">"#
|
||||
));
|
||||
svg.push_str(&format!(
|
||||
r#"<rect width="{total}" height="{total}" fill="{bg}"/>"#
|
||||
r#"<rect width="{total}" height="{total}" fill="{bg_hex}"/>"#
|
||||
));
|
||||
|
||||
for y in 0..matrix_size {
|
||||
for x in 0..matrix_size {
|
||||
if qr.modules()[y as usize][x as usize] {
|
||||
svg.push_str(&format!(
|
||||
r#"<rect x="{}" y="{}" width="1" height="1" fill="{fg}"/>"#,
|
||||
r#"<rect x="{}" y="{}" width="1" height="1" fill="{fg_hex}"/>"#,
|
||||
x + margin,
|
||||
y + margin
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user