Skip to content

Commit 4b1d089

Browse files
committed
fix: 修复所有问题
1 parent 70fa8c6 commit 4b1d089

File tree

1 file changed

+121
-104
lines changed

1 file changed

+121
-104
lines changed

src/colorful.rs

Lines changed: 121 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ fn mm_to_mil_10(val: f64) -> f64 {
225225
}
226226

227227
fn compute_mark_points(bounds: &BoardBounds) -> Vec<(f64, f64)> {
228-
// Inset by approximately 3 mil to mirror the original script behaviour.
228+
// Inset by approximately 3 mil (0.0762mm) to mirror the original script behaviour.
229229
const INSET_MM: f64 = 0.0762;
230230
let min_x = bounds.min_x + INSET_MM;
231231
let max_x = bounds.max_x - INSET_MM;
@@ -236,26 +236,37 @@ fn compute_mark_points(bounds: &BoardBounds) -> Vec<(f64, f64)> {
236236
}
237237

238238
fn build_bottom_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
239-
let ox = mm_to_mil_10(bounds.origin_x);
240-
let oy = mm_to_mil_10(bounds.origin_y);
239+
const CLIP_MARGIN: f64 = 0.8374; // shrink (10 mil units)
240+
const EXPAND: f64 = 0.5; // expand (10 mil units)
241+
242+
let min_x = mm_to_mil_10(bounds.min_x);
243+
let max_x = mm_to_mil_10(bounds.max_x);
244+
// Y axis in the reference SVG is inverted: use -max_y as the min value and
245+
// -min_y as the max value, while keeping width/height unchanged.
246+
let min_y = -mm_to_mil_10(bounds.max_y);
247+
let max_y = -mm_to_mil_10(bounds.min_y);
241248
let w = mm_to_mil_10(bounds.width);
242249
let h = mm_to_mil_10(bounds.height);
250+
let center_x = min_x + w / 2.0;
243251
let image_w = image.width;
244252
let image_h = image.height;
245253

254+
let mark_points = compute_mark_points(bounds)
255+
.iter()
256+
.flat_map(|(x, y)| [mm_to_mil_10(*x).to_string(), mm_to_mil_10(*y).to_string()])
257+
.collect::<Vec<_>>()
258+
.join(" ");
259+
246260
let mut writer = create_writer();
247261

248262
writer.start_element("svg");
249263
writer.write_attribute("width", &format!("{}mm", bounds.width));
250264
writer.write_attribute("height", &format!("{}mm", bounds.height));
251-
writer.write_attribute("boardBox", &format!("{} {} {} {}", ox, oy + h, w, h));
252-
writer.write_attribute("viewBox", &format!("{} {} {} {}", ox, oy + h, w, h));
265+
writer.write_attribute("boardBox", &format!("{min_x} {min_y} {w} {h}"));
266+
writer.write_attribute("viewBox", &format!("{min_x} {min_y} {w} {h}"));
253267
writer.write_attribute("version", "1.1");
254268
writer.write_attribute("eda-version", "1.6(2025-08-27)");
255-
writer.write_attribute(
256-
"mark-points",
257-
"-115.11024 -36.37008 -115.11024 154.48031000000003 193.85038999999998 154.48031",
258-
);
269+
writer.write_attribute("mark-points", &mark_points);
259270
writer.write_attribute(
260271
"xmlns:inkscape",
261272
"http://www.inkscape.org/namespaces/inkscape",
@@ -268,7 +279,7 @@ fn build_bottom_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
268279
writer.write_attribute("xmlns", "http://www.w3.org/2000/svg");
269280
writer.write_attribute("xmlns:svg", "http://www.w3.org/2000/svg");
270281

271-
// defs/clipPath 0
282+
// clipPath0 shrink
272283
writer.start_element("defs");
273284
writer.start_element("clipPath");
274285
writer.write_attribute("id", "clipPath0");
@@ -277,26 +288,26 @@ fn build_bottom_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
277288
"d",
278289
&format!(
279290
"M {} {} L {} {} {} {} {} {} {} {} ",
280-
ox + w - 0.05,
281-
-oy - 0.05, // svg中y轴向下递增
282-
ox + 0.05,
283-
-oy - 0.05,
284-
ox + 0.05,
285-
-(oy + h) - 0.05,
286-
ox + w - 0.05,
287-
-(oy + h) - 0.05,
288-
ox + w - 0.05,
289-
-oy - 0.05,
291+
max_x - CLIP_MARGIN,
292+
max_y - CLIP_MARGIN,
293+
min_x + CLIP_MARGIN,
294+
max_y - CLIP_MARGIN,
295+
min_x + CLIP_MARGIN,
296+
min_y + CLIP_MARGIN,
297+
max_x - CLIP_MARGIN,
298+
min_y + CLIP_MARGIN,
299+
max_x - CLIP_MARGIN,
300+
max_y - CLIP_MARGIN
290301
),
291302
);
292303
writer.write_attribute("id", "outline0");
293304
writer.write_attribute("stroke", "none");
294305
writer.write_attribute("style", "fill-opacity:1;fill-rule:nonzero;fill:block;");
295-
writer.end_element(); // path
296-
writer.end_element(); // clipPath
297-
writer.end_element(); // defs
306+
writer.end_element();
307+
writer.end_element();
308+
writer.end_element();
298309

299-
// defs/clipPath 1
310+
// clipPath1 expand
300311
writer.start_element("defs");
301312
writer.start_element("clipPath");
302313
writer.write_attribute("id", "clipPath1");
@@ -306,55 +317,55 @@ fn build_bottom_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
306317
"d",
307318
&format!(
308319
"M {} {} L {} {} {} {} {} {} {} {} ",
309-
ox + w + 0.05,
310-
-(oy + h) + 0.05, // svg中y轴向下递增
311-
ox + w + 0.05,
312-
-oy + 0.05,
313-
ox - 0.05,
314-
-oy + 0.05,
315-
ox - 0.05,
316-
-(oy + h) + 0.05,
317-
ox + w + 0.05,
318-
-(oy + h) + 0.05,
320+
max_x + EXPAND,
321+
min_y - EXPAND,
322+
max_x + EXPAND,
323+
max_y + EXPAND,
324+
min_x - EXPAND,
325+
max_y + EXPAND,
326+
min_x - EXPAND,
327+
min_y - EXPAND,
328+
max_x + EXPAND,
329+
min_y - EXPAND
319330
),
320331
);
321332
writer.write_attribute("id", "solder1");
322333
writer.write_attribute("stroke", "none");
323334
writer.write_attribute("style", "fill-opacity:1;fill-rule:nonzero;fill:block;");
324-
writer.end_element(); // path
325-
writer.end_element(); // clipPath
326-
writer.end_element(); // defs
335+
writer.end_element();
336+
writer.end_element();
337+
writer.end_element();
327338

328-
// main group
339+
// main group (mirrored)
329340
writer.start_element("g");
330341
writer.write_attribute("clip-path", "url(#clipPath1)");
331342
writer.write_attribute(
332343
"transform",
333-
&format!("scale(-1 1) translate({} 0)", -((oy + h) / 2f64)),
344+
&format!("scale(-1 1) translate({} 0)", -2.0 * center_x),
334345
);
335346

336347
writer.start_element("path");
337348
writer.write_attribute(
338349
"d",
339350
&format!(
340351
"M {} {} L {} {} {} {} {} {} {} {} ",
341-
ox - 0.05,
342-
-oy + 0.05,
343-
ox - 0.05,
344-
-(oy + h) + 0.05,
345-
ox + w + 0.05,
346-
-(oy + h) + 0.05,
347-
ox + w + 0.05,
348-
-oy + 0.05,
349-
ox - 0.05,
350-
-oy + 0.05,
352+
min_x - EXPAND,
353+
max_y + EXPAND,
354+
min_x - EXPAND,
355+
min_y - EXPAND,
356+
max_x + EXPAND,
357+
min_y - EXPAND,
358+
max_x + EXPAND,
359+
max_y + EXPAND,
360+
min_x - EXPAND,
361+
max_y + EXPAND
351362
),
352363
);
353364
writer.write_attribute("fill", "#FFFFFF");
354365
writer.write_attribute("stroke", "none");
355366
writer.write_attribute("stroke-width", "0");
356367
writer.write_attribute("id", "background");
357-
writer.end_element(); // path
368+
writer.end_element();
358369

359370
writer.start_element("image");
360371
writer.write_attribute("width", &image_w.to_string());
@@ -367,8 +378,8 @@ fn build_bottom_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
367378
"matrix({} 0 0 {} {} {})",
368379
-(w / image_w as f64),
369380
h / image_h as f64,
370-
h,
371-
-(oy + h)
381+
max_x,
382+
min_y
372383
),
373384
);
374385
writer.end_element(); // image
@@ -460,26 +471,35 @@ fn format_coord(x_mm: f64, y_mm: f64) -> (String, String) {
460471
}
461472

462473
fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
463-
let ox = mm_to_mil_10(bounds.origin_x);
464-
let oy = mm_to_mil_10(bounds.origin_y);
474+
const CLIP_MARGIN: f64 = 0.8374; // in 10-mil units
475+
const EXPAND: f64 = 0.5; // in 10-mil units
476+
477+
// Convert mm to 10-mil units (as used by sample SVGs)
478+
let min_x = mm_to_mil_10(bounds.min_x);
479+
let max_x = mm_to_mil_10(bounds.max_x);
480+
let min_y = -mm_to_mil_10(bounds.max_y);
481+
let max_y = -mm_to_mil_10(bounds.min_y);
465482
let w = mm_to_mil_10(bounds.width);
466483
let h = mm_to_mil_10(bounds.height);
467484
let image_w = image.width;
468485
let image_h = image.height;
469486

487+
let mark_points = compute_mark_points(bounds)
488+
.iter()
489+
.flat_map(|(x, y)| [mm_to_mil_10(*x).to_string(), mm_to_mil_10(*y).to_string()])
490+
.collect::<Vec<_>>()
491+
.join(" ");
492+
470493
let mut writer = create_writer();
471494

472495
writer.start_element("svg");
473496
writer.write_attribute("width", &format!("{}mm", bounds.width));
474497
writer.write_attribute("height", &format!("{}mm", bounds.height));
475-
writer.write_attribute("boardBox", &format!("{} {} {} {}", ox, -(oy + h), w, h));
476-
writer.write_attribute("viewBox", &format!("{} {} {} {}", ox, -(oy + h), w, h));
498+
writer.write_attribute("boardBox", &format!("{min_x} {min_y} {w} {h}"));
499+
writer.write_attribute("viewBox", &format!("{min_x} {min_y} {w} {h}"));
477500
writer.write_attribute("version", "1.1");
478501
writer.write_attribute("eda-version", "1.6(2025-08-27)");
479-
writer.write_attribute(
480-
"mark-points",
481-
"-115.11024 -36.37008 -115.11024 154.48031000000003 193.85038999999998 154.48031",
482-
);
502+
writer.write_attribute("mark-points", &mark_points);
483503
writer.write_attribute(
484504
"xmlns:inkscape",
485505
"http://www.inkscape.org/namespaces/inkscape",
@@ -492,7 +512,6 @@ fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
492512
writer.write_attribute("xmlns", "http://www.w3.org/2000/svg");
493513
writer.write_attribute("xmlns:svg", "http://www.w3.org/2000/svg");
494514

495-
// defs/clipPath 0
496515
writer.start_element("defs");
497516
writer.start_element("clipPath");
498517
writer.write_attribute("id", "clipPath0");
@@ -501,16 +520,16 @@ fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
501520
"d",
502521
&format!(
503522
"M {} {} L {} {} {} {} {} {} {} {} ",
504-
ox + w - 0.05,
505-
-oy - 0.05, // svg中y轴向下递增
506-
ox + 0.05,
507-
-oy - 0.05,
508-
ox + 0.05,
509-
-(oy + h) - 0.05,
510-
ox + w - 0.05,
511-
-(oy + h) - 0.05,
512-
ox + w - 0.05,
513-
-oy - 0.05,
523+
max_x - CLIP_MARGIN,
524+
max_y - CLIP_MARGIN,
525+
min_x + CLIP_MARGIN,
526+
max_y - CLIP_MARGIN,
527+
min_x + CLIP_MARGIN,
528+
min_y + CLIP_MARGIN,
529+
max_x - CLIP_MARGIN,
530+
min_y + CLIP_MARGIN,
531+
max_x - CLIP_MARGIN,
532+
max_y - CLIP_MARGIN
514533
),
515534
);
516535
writer.write_attribute("id", "outline0");
@@ -520,7 +539,6 @@ fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
520539
writer.end_element(); // clipPath
521540
writer.end_element(); // defs
522541

523-
// defs/clipPath 1
524542
writer.start_element("defs");
525543
writer.start_element("clipPath");
526544
writer.write_attribute("id", "clipPath1");
@@ -530,26 +548,25 @@ fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
530548
"d",
531549
&format!(
532550
"M {} {} L {} {} {} {} {} {} {} {} ",
533-
ox + w + 0.05,
534-
-(oy + h) + 0.05, // svg中y轴向下递增
535-
ox + w + 0.05,
536-
-oy + 0.05,
537-
ox - 0.05,
538-
-oy + 0.05,
539-
ox - 0.05,
540-
-(oy + h) + 0.05,
541-
ox + w + 0.05,
542-
-(oy + h) + 0.05,
551+
max_x + EXPAND,
552+
min_y - EXPAND,
553+
max_x + EXPAND,
554+
max_y + EXPAND,
555+
min_x - EXPAND,
556+
max_y + EXPAND,
557+
min_x - EXPAND,
558+
min_y - EXPAND,
559+
max_x + EXPAND,
560+
min_y - EXPAND
543561
),
544562
);
545563
writer.write_attribute("id", "solder1");
546564
writer.write_attribute("stroke", "none");
547-
writer.write_attribute("style", "fill-opacity:1;fill-rule:nonzero;fill:block");
565+
writer.write_attribute("style", "fill-opacity:1;fill-rule:nonzero;fill:block;");
548566
writer.end_element(); // path
549567
writer.end_element(); // clipPath
550568
writer.end_element(); // defs
551569

552-
// main group
553570
writer.start_element("g");
554571
writer.write_attribute("clip-path", "url(#clipPath1)");
555572
writer.write_attribute("transform", "scale(1 1) translate(0 0)");
@@ -559,16 +576,16 @@ fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
559576
"d",
560577
&format!(
561578
"M {} {} L {} {} {} {} {} {} {} {} ",
562-
ox - 0.05,
563-
-oy + 0.05,
564-
ox - 0.05,
565-
-(oy + h) + 0.05,
566-
ox + w + 0.05,
567-
-(oy + h) + 0.05,
568-
ox + w + 0.05,
569-
-oy + 0.05,
570-
ox - 0.05,
571-
-oy + 0.05,
579+
min_x - EXPAND,
580+
max_y + EXPAND,
581+
min_x - EXPAND,
582+
min_y - EXPAND,
583+
max_x + EXPAND,
584+
min_y - EXPAND,
585+
max_x + EXPAND,
586+
max_y + EXPAND,
587+
min_x - EXPAND,
588+
max_y + EXPAND
572589
),
573590
);
574591
writer.write_attribute("fill", "#FFFFFF");
@@ -577,19 +594,19 @@ fn build_top_svg(bounds: &BoardBounds, image: &SilkscreenImage) -> String {
577594
writer.write_attribute("id", "background");
578595
writer.end_element(); // path
579596

580-
writer.start_element("image");
581-
writer.write_attribute("width", &image_w.to_string());
582-
writer.write_attribute("height", &image_h.to_string());
583-
writer.write_attribute("preserveAspectRatio", "none");
584-
writer.write_attribute("xlink:href", &image.data_uri);
585-
writer.write_attribute(
586-
"transform",
587-
&format!(
597+
writer.start_element("image");
598+
writer.write_attribute("width", &image_w.to_string());
599+
writer.write_attribute("height", &image_h.to_string());
600+
writer.write_attribute("preserveAspectRatio", "none");
601+
writer.write_attribute("xlink:href", &image.data_uri);
602+
writer.write_attribute(
603+
"transform",
604+
&format!(
588605
"matrix({} 0 0 {} {} {})",
589606
w / image_w as f64,
590607
h / image_h as f64,
591-
ox,
592-
-(oy + h)
608+
min_x,
609+
min_y
593610
),
594611
);
595612
writer.end_element(); // image

0 commit comments

Comments
 (0)