circuit-to-canvas 0.0.36 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +429 -275
- package/lib/drawer/CircuitToCanvasDrawer.ts +7 -1
- package/lib/drawer/elements/pcb-plated-hole.ts +203 -7
- package/lib/drawer/shapes/dimension-line.ts +74 -79
- package/package.json +1 -1
- package/tests/elements/__snapshots__/pcb-fabrication-note-dimension.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-plated-hole-soldermask-margin.snap.png +0 -0
- package/tests/elements/pcb-plated-hole-soldermask-margin.test.ts +225 -0
package/dist/index.js
CHANGED
|
@@ -249,17 +249,252 @@ function drawPolygon(params) {
|
|
|
249
249
|
ctx.fill();
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
// lib/drawer/elements/soldermask-margin.ts
|
|
253
|
+
import { applyToPoint as applyToPoint6 } from "transformation-matrix";
|
|
254
|
+
function drawSoldermaskRingForRect(ctx, center, width, height, margin, borderRadius, rotation, realToCanvasMat, soldermaskColor, padColor) {
|
|
255
|
+
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
256
|
+
const scaledWidth = width * Math.abs(realToCanvasMat.a);
|
|
257
|
+
const scaledHeight = height * Math.abs(realToCanvasMat.a);
|
|
258
|
+
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
259
|
+
const scaledRadius = borderRadius * Math.abs(realToCanvasMat.a);
|
|
260
|
+
ctx.save();
|
|
261
|
+
ctx.translate(cx, cy);
|
|
262
|
+
if (rotation !== 0) {
|
|
263
|
+
ctx.rotate(-rotation * (Math.PI / 180));
|
|
264
|
+
}
|
|
265
|
+
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
266
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
267
|
+
ctx.globalCompositeOperation = "source-atop";
|
|
268
|
+
}
|
|
269
|
+
const outerWidth = scaledWidth;
|
|
270
|
+
const outerHeight = scaledHeight;
|
|
271
|
+
const outerRadius = scaledRadius;
|
|
272
|
+
ctx.beginPath();
|
|
273
|
+
if (outerRadius > 0) {
|
|
274
|
+
const x = -outerWidth / 2;
|
|
275
|
+
const y = -outerHeight / 2;
|
|
276
|
+
const r = Math.min(outerRadius, outerWidth / 2, outerHeight / 2);
|
|
277
|
+
ctx.moveTo(x + r, y);
|
|
278
|
+
ctx.lineTo(x + outerWidth - r, y);
|
|
279
|
+
ctx.arcTo(x + outerWidth, y, x + outerWidth, y + r, r);
|
|
280
|
+
ctx.lineTo(x + outerWidth, y + outerHeight - r);
|
|
281
|
+
ctx.arcTo(
|
|
282
|
+
x + outerWidth,
|
|
283
|
+
y + outerHeight,
|
|
284
|
+
x + outerWidth - r,
|
|
285
|
+
y + outerHeight,
|
|
286
|
+
r
|
|
287
|
+
);
|
|
288
|
+
ctx.lineTo(x + r, y + outerHeight);
|
|
289
|
+
ctx.arcTo(x, y + outerHeight, x, y + outerHeight - r, r);
|
|
290
|
+
ctx.lineTo(x, y + r);
|
|
291
|
+
ctx.arcTo(x, y, x + r, y, r);
|
|
292
|
+
} else {
|
|
293
|
+
ctx.rect(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight);
|
|
294
|
+
}
|
|
295
|
+
ctx.fillStyle = soldermaskColor;
|
|
296
|
+
ctx.fill();
|
|
297
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
298
|
+
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
299
|
+
}
|
|
300
|
+
const innerWidth = scaledWidth - scaledMargin * 2;
|
|
301
|
+
const innerHeight = scaledHeight - scaledMargin * 2;
|
|
302
|
+
const innerRadius = Math.max(0, scaledRadius - scaledMargin);
|
|
303
|
+
if (innerWidth > 0 && innerHeight > 0) {
|
|
304
|
+
ctx.beginPath();
|
|
305
|
+
if (innerRadius > 0) {
|
|
306
|
+
const x = -innerWidth / 2;
|
|
307
|
+
const y = -innerHeight / 2;
|
|
308
|
+
const r = Math.min(innerRadius, innerWidth / 2, innerHeight / 2);
|
|
309
|
+
ctx.moveTo(x + r, y);
|
|
310
|
+
ctx.lineTo(x + innerWidth - r, y);
|
|
311
|
+
ctx.arcTo(x + innerWidth, y, x + innerWidth, y + r, r);
|
|
312
|
+
ctx.lineTo(x + innerWidth, y + innerHeight - r);
|
|
313
|
+
ctx.arcTo(
|
|
314
|
+
x + innerWidth,
|
|
315
|
+
y + innerHeight,
|
|
316
|
+
x + innerWidth - r,
|
|
317
|
+
y + innerHeight,
|
|
318
|
+
r
|
|
319
|
+
);
|
|
320
|
+
ctx.lineTo(x + r, y + innerHeight);
|
|
321
|
+
ctx.arcTo(x, y + innerHeight, x, y + innerHeight - r, r);
|
|
322
|
+
ctx.lineTo(x, y + r);
|
|
323
|
+
ctx.arcTo(x, y, x + r, y, r);
|
|
324
|
+
} else {
|
|
325
|
+
ctx.rect(-innerWidth / 2, -innerHeight / 2, innerWidth, innerHeight);
|
|
326
|
+
}
|
|
327
|
+
ctx.fillStyle = padColor;
|
|
328
|
+
ctx.fill();
|
|
329
|
+
}
|
|
330
|
+
ctx.restore();
|
|
331
|
+
}
|
|
332
|
+
function drawSoldermaskRingForCircle(ctx, center, radius, margin, realToCanvasMat, soldermaskColor, padColor) {
|
|
333
|
+
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
334
|
+
const scaledRadius = radius * Math.abs(realToCanvasMat.a);
|
|
335
|
+
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
336
|
+
ctx.save();
|
|
337
|
+
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
338
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
339
|
+
ctx.globalCompositeOperation = "source-atop";
|
|
340
|
+
}
|
|
341
|
+
ctx.beginPath();
|
|
342
|
+
ctx.arc(cx, cy, scaledRadius, 0, Math.PI * 2);
|
|
343
|
+
ctx.fillStyle = soldermaskColor;
|
|
344
|
+
ctx.fill();
|
|
345
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
346
|
+
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
347
|
+
}
|
|
348
|
+
const innerRadius = Math.max(0, scaledRadius - scaledMargin);
|
|
349
|
+
if (innerRadius > 0) {
|
|
350
|
+
ctx.beginPath();
|
|
351
|
+
ctx.arc(cx, cy, innerRadius, 0, Math.PI * 2);
|
|
352
|
+
ctx.fillStyle = padColor;
|
|
353
|
+
ctx.fill();
|
|
354
|
+
}
|
|
355
|
+
ctx.restore();
|
|
356
|
+
}
|
|
357
|
+
function drawSoldermaskRingForPill(ctx, center, width, height, margin, rotation, realToCanvasMat, soldermaskColor, padColor) {
|
|
358
|
+
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
359
|
+
const scaledWidth = width * Math.abs(realToCanvasMat.a);
|
|
360
|
+
const scaledHeight = height * Math.abs(realToCanvasMat.a);
|
|
361
|
+
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
362
|
+
ctx.save();
|
|
363
|
+
ctx.translate(cx, cy);
|
|
364
|
+
if (rotation !== 0) {
|
|
365
|
+
ctx.rotate(-rotation * (Math.PI / 180));
|
|
366
|
+
}
|
|
367
|
+
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
368
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
369
|
+
ctx.globalCompositeOperation = "source-atop";
|
|
370
|
+
}
|
|
371
|
+
const outerWidth = scaledWidth;
|
|
372
|
+
const outerHeight = scaledHeight;
|
|
373
|
+
ctx.beginPath();
|
|
374
|
+
if (outerWidth > outerHeight) {
|
|
375
|
+
const radius = outerHeight / 2;
|
|
376
|
+
const straightLength = outerWidth - outerHeight;
|
|
377
|
+
ctx.moveTo(-straightLength / 2, -radius);
|
|
378
|
+
ctx.lineTo(straightLength / 2, -radius);
|
|
379
|
+
ctx.arc(straightLength / 2, 0, radius, -Math.PI / 2, Math.PI / 2);
|
|
380
|
+
ctx.lineTo(-straightLength / 2, radius);
|
|
381
|
+
ctx.arc(-straightLength / 2, 0, radius, Math.PI / 2, -Math.PI / 2);
|
|
382
|
+
} else if (outerHeight > outerWidth) {
|
|
383
|
+
const radius = outerWidth / 2;
|
|
384
|
+
const straightLength = outerHeight - outerWidth;
|
|
385
|
+
ctx.moveTo(radius, -straightLength / 2);
|
|
386
|
+
ctx.lineTo(radius, straightLength / 2);
|
|
387
|
+
ctx.arc(0, straightLength / 2, radius, 0, Math.PI);
|
|
388
|
+
ctx.lineTo(-radius, -straightLength / 2);
|
|
389
|
+
ctx.arc(0, -straightLength / 2, radius, Math.PI, 0);
|
|
390
|
+
} else {
|
|
391
|
+
ctx.arc(0, 0, outerWidth / 2, 0, Math.PI * 2);
|
|
392
|
+
}
|
|
393
|
+
ctx.fillStyle = soldermaskColor;
|
|
394
|
+
ctx.fill();
|
|
395
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
396
|
+
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
397
|
+
}
|
|
398
|
+
const innerWidth = scaledWidth - scaledMargin * 2;
|
|
399
|
+
const innerHeight = scaledHeight - scaledMargin * 2;
|
|
400
|
+
if (innerWidth > 0 && innerHeight > 0) {
|
|
401
|
+
ctx.beginPath();
|
|
402
|
+
if (innerWidth > innerHeight) {
|
|
403
|
+
const radius = innerHeight / 2;
|
|
404
|
+
const straightLength = innerWidth - innerHeight;
|
|
405
|
+
ctx.moveTo(-straightLength / 2, -radius);
|
|
406
|
+
ctx.lineTo(straightLength / 2, -radius);
|
|
407
|
+
ctx.arc(straightLength / 2, 0, radius, -Math.PI / 2, Math.PI / 2);
|
|
408
|
+
ctx.lineTo(-straightLength / 2, radius);
|
|
409
|
+
ctx.arc(-straightLength / 2, 0, radius, Math.PI / 2, -Math.PI / 2);
|
|
410
|
+
} else if (innerHeight > innerWidth) {
|
|
411
|
+
const radius = innerWidth / 2;
|
|
412
|
+
const straightLength = innerHeight - innerWidth;
|
|
413
|
+
ctx.moveTo(radius, -straightLength / 2);
|
|
414
|
+
ctx.lineTo(radius, straightLength / 2);
|
|
415
|
+
ctx.arc(0, straightLength / 2, radius, 0, Math.PI);
|
|
416
|
+
ctx.lineTo(-radius, -straightLength / 2);
|
|
417
|
+
ctx.arc(0, -straightLength / 2, radius, Math.PI, 0);
|
|
418
|
+
} else {
|
|
419
|
+
ctx.arc(0, 0, innerWidth / 2, 0, Math.PI * 2);
|
|
420
|
+
}
|
|
421
|
+
ctx.fillStyle = padColor;
|
|
422
|
+
ctx.fill();
|
|
423
|
+
}
|
|
424
|
+
ctx.restore();
|
|
425
|
+
}
|
|
426
|
+
function drawSoldermaskRingForOval(ctx, center, radius_x, radius_y, margin, rotation, realToCanvasMat, soldermaskColor, holeColor) {
|
|
427
|
+
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
428
|
+
const scaledRadiusX = radius_x * Math.abs(realToCanvasMat.a);
|
|
429
|
+
const scaledRadiusY = radius_y * Math.abs(realToCanvasMat.a);
|
|
430
|
+
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
431
|
+
ctx.save();
|
|
432
|
+
ctx.translate(cx, cy);
|
|
433
|
+
if (rotation !== 0) {
|
|
434
|
+
ctx.rotate(-rotation * (Math.PI / 180));
|
|
435
|
+
}
|
|
436
|
+
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
437
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
438
|
+
ctx.globalCompositeOperation = "source-atop";
|
|
439
|
+
}
|
|
440
|
+
ctx.beginPath();
|
|
441
|
+
ctx.ellipse(0, 0, scaledRadiusX, scaledRadiusY, 0, 0, Math.PI * 2);
|
|
442
|
+
ctx.fillStyle = soldermaskColor;
|
|
443
|
+
ctx.fill();
|
|
444
|
+
if (ctx.globalCompositeOperation !== void 0) {
|
|
445
|
+
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
446
|
+
}
|
|
447
|
+
const innerRadiusX = Math.max(0, scaledRadiusX - scaledMargin);
|
|
448
|
+
const innerRadiusY = Math.max(0, scaledRadiusY - scaledMargin);
|
|
449
|
+
if (innerRadiusX > 0 && innerRadiusY > 0) {
|
|
450
|
+
ctx.beginPath();
|
|
451
|
+
ctx.ellipse(0, 0, innerRadiusX, innerRadiusY, 0, 0, Math.PI * 2);
|
|
452
|
+
ctx.fillStyle = holeColor;
|
|
453
|
+
ctx.fill();
|
|
454
|
+
}
|
|
455
|
+
ctx.restore();
|
|
456
|
+
}
|
|
457
|
+
|
|
252
458
|
// lib/drawer/elements/pcb-plated-hole.ts
|
|
459
|
+
function getSoldermaskColor(layers, colorMap) {
|
|
460
|
+
const layer = layers?.includes("top") ? "top" : "bottom";
|
|
461
|
+
return colorMap.soldermaskOverCopper[layer] ?? colorMap.soldermaskOverCopper.top;
|
|
462
|
+
}
|
|
253
463
|
function drawPcbPlatedHole(params) {
|
|
254
464
|
const { ctx, hole, realToCanvasMat, colorMap } = params;
|
|
465
|
+
const hasSoldermask = hole.is_covered_with_solder_mask === true && hole.soldermask_margin !== void 0 && hole.soldermask_margin !== 0;
|
|
466
|
+
const margin = hasSoldermask ? hole.soldermask_margin : 0;
|
|
467
|
+
const soldermaskRingColor = getSoldermaskColor(hole.layers, colorMap);
|
|
468
|
+
const positiveMarginColor = colorMap.substrate;
|
|
469
|
+
const copperColor = colorMap.copper.top;
|
|
255
470
|
if (hole.shape === "circle") {
|
|
471
|
+
if (hasSoldermask && margin > 0) {
|
|
472
|
+
drawCircle({
|
|
473
|
+
ctx,
|
|
474
|
+
center: { x: hole.x, y: hole.y },
|
|
475
|
+
radius: hole.outer_diameter / 2 + margin,
|
|
476
|
+
fill: positiveMarginColor,
|
|
477
|
+
realToCanvasMat
|
|
478
|
+
});
|
|
479
|
+
}
|
|
256
480
|
drawCircle({
|
|
257
481
|
ctx,
|
|
258
482
|
center: { x: hole.x, y: hole.y },
|
|
259
483
|
radius: hole.outer_diameter / 2,
|
|
260
|
-
fill:
|
|
484
|
+
fill: copperColor,
|
|
261
485
|
realToCanvasMat
|
|
262
486
|
});
|
|
487
|
+
if (hasSoldermask && margin < 0) {
|
|
488
|
+
drawSoldermaskRingForCircle(
|
|
489
|
+
ctx,
|
|
490
|
+
{ x: hole.x, y: hole.y },
|
|
491
|
+
hole.outer_diameter / 2,
|
|
492
|
+
margin,
|
|
493
|
+
realToCanvasMat,
|
|
494
|
+
soldermaskRingColor,
|
|
495
|
+
copperColor
|
|
496
|
+
);
|
|
497
|
+
}
|
|
263
498
|
drawCircle({
|
|
264
499
|
ctx,
|
|
265
500
|
center: { x: hole.x, y: hole.y },
|
|
@@ -270,15 +505,39 @@ function drawPcbPlatedHole(params) {
|
|
|
270
505
|
return;
|
|
271
506
|
}
|
|
272
507
|
if (hole.shape === "oval") {
|
|
508
|
+
if (hasSoldermask && margin > 0) {
|
|
509
|
+
drawOval({
|
|
510
|
+
ctx,
|
|
511
|
+
center: { x: hole.x, y: hole.y },
|
|
512
|
+
radius_x: hole.outer_width / 2 + margin,
|
|
513
|
+
radius_y: hole.outer_height / 2 + margin,
|
|
514
|
+
fill: positiveMarginColor,
|
|
515
|
+
realToCanvasMat,
|
|
516
|
+
rotation: hole.ccw_rotation
|
|
517
|
+
});
|
|
518
|
+
}
|
|
273
519
|
drawOval({
|
|
274
520
|
ctx,
|
|
275
521
|
center: { x: hole.x, y: hole.y },
|
|
276
522
|
radius_x: hole.outer_width / 2,
|
|
277
523
|
radius_y: hole.outer_height / 2,
|
|
278
|
-
fill:
|
|
524
|
+
fill: copperColor,
|
|
279
525
|
realToCanvasMat,
|
|
280
526
|
rotation: hole.ccw_rotation
|
|
281
527
|
});
|
|
528
|
+
if (hasSoldermask && margin < 0) {
|
|
529
|
+
drawSoldermaskRingForOval(
|
|
530
|
+
ctx,
|
|
531
|
+
{ x: hole.x, y: hole.y },
|
|
532
|
+
hole.outer_width / 2,
|
|
533
|
+
hole.outer_height / 2,
|
|
534
|
+
margin,
|
|
535
|
+
hole.ccw_rotation ?? 0,
|
|
536
|
+
realToCanvasMat,
|
|
537
|
+
soldermaskRingColor,
|
|
538
|
+
copperColor
|
|
539
|
+
);
|
|
540
|
+
}
|
|
282
541
|
drawOval({
|
|
283
542
|
ctx,
|
|
284
543
|
center: { x: hole.x, y: hole.y },
|
|
@@ -291,15 +550,39 @@ function drawPcbPlatedHole(params) {
|
|
|
291
550
|
return;
|
|
292
551
|
}
|
|
293
552
|
if (hole.shape === "pill") {
|
|
553
|
+
if (hasSoldermask && margin > 0) {
|
|
554
|
+
drawPill({
|
|
555
|
+
ctx,
|
|
556
|
+
center: { x: hole.x, y: hole.y },
|
|
557
|
+
width: hole.outer_width + margin * 2,
|
|
558
|
+
height: hole.outer_height + margin * 2,
|
|
559
|
+
fill: positiveMarginColor,
|
|
560
|
+
realToCanvasMat,
|
|
561
|
+
rotation: hole.ccw_rotation
|
|
562
|
+
});
|
|
563
|
+
}
|
|
294
564
|
drawPill({
|
|
295
565
|
ctx,
|
|
296
566
|
center: { x: hole.x, y: hole.y },
|
|
297
567
|
width: hole.outer_width,
|
|
298
568
|
height: hole.outer_height,
|
|
299
|
-
fill:
|
|
569
|
+
fill: copperColor,
|
|
300
570
|
realToCanvasMat,
|
|
301
571
|
rotation: hole.ccw_rotation
|
|
302
572
|
});
|
|
573
|
+
if (hasSoldermask && margin < 0) {
|
|
574
|
+
drawSoldermaskRingForPill(
|
|
575
|
+
ctx,
|
|
576
|
+
{ x: hole.x, y: hole.y },
|
|
577
|
+
hole.outer_width,
|
|
578
|
+
hole.outer_height,
|
|
579
|
+
margin,
|
|
580
|
+
hole.ccw_rotation ?? 0,
|
|
581
|
+
realToCanvasMat,
|
|
582
|
+
soldermaskRingColor,
|
|
583
|
+
copperColor
|
|
584
|
+
);
|
|
585
|
+
}
|
|
303
586
|
drawPill({
|
|
304
587
|
ctx,
|
|
305
588
|
center: { x: hole.x, y: hole.y },
|
|
@@ -312,15 +595,40 @@ function drawPcbPlatedHole(params) {
|
|
|
312
595
|
return;
|
|
313
596
|
}
|
|
314
597
|
if (hole.shape === "circular_hole_with_rect_pad") {
|
|
598
|
+
if (hasSoldermask && margin > 0) {
|
|
599
|
+
drawRect({
|
|
600
|
+
ctx,
|
|
601
|
+
center: { x: hole.x, y: hole.y },
|
|
602
|
+
width: hole.rect_pad_width + margin * 2,
|
|
603
|
+
height: hole.rect_pad_height + margin * 2,
|
|
604
|
+
fill: positiveMarginColor,
|
|
605
|
+
realToCanvasMat,
|
|
606
|
+
borderRadius: (hole.rect_border_radius ?? 0) + margin
|
|
607
|
+
});
|
|
608
|
+
}
|
|
315
609
|
drawRect({
|
|
316
610
|
ctx,
|
|
317
611
|
center: { x: hole.x, y: hole.y },
|
|
318
612
|
width: hole.rect_pad_width,
|
|
319
613
|
height: hole.rect_pad_height,
|
|
320
|
-
fill:
|
|
614
|
+
fill: copperColor,
|
|
321
615
|
realToCanvasMat,
|
|
322
616
|
borderRadius: hole.rect_border_radius ?? 0
|
|
323
617
|
});
|
|
618
|
+
if (hasSoldermask && margin < 0) {
|
|
619
|
+
drawSoldermaskRingForRect(
|
|
620
|
+
ctx,
|
|
621
|
+
{ x: hole.x, y: hole.y },
|
|
622
|
+
hole.rect_pad_width,
|
|
623
|
+
hole.rect_pad_height,
|
|
624
|
+
margin,
|
|
625
|
+
hole.rect_border_radius ?? 0,
|
|
626
|
+
0,
|
|
627
|
+
realToCanvasMat,
|
|
628
|
+
soldermaskRingColor,
|
|
629
|
+
copperColor
|
|
630
|
+
);
|
|
631
|
+
}
|
|
324
632
|
const holeX = hole.x + (hole.hole_offset_x ?? 0);
|
|
325
633
|
const holeY = hole.y + (hole.hole_offset_y ?? 0);
|
|
326
634
|
drawCircle({
|
|
@@ -333,15 +641,40 @@ function drawPcbPlatedHole(params) {
|
|
|
333
641
|
return;
|
|
334
642
|
}
|
|
335
643
|
if (hole.shape === "pill_hole_with_rect_pad") {
|
|
644
|
+
if (hasSoldermask && margin > 0) {
|
|
645
|
+
drawRect({
|
|
646
|
+
ctx,
|
|
647
|
+
center: { x: hole.x, y: hole.y },
|
|
648
|
+
width: hole.rect_pad_width + margin * 2,
|
|
649
|
+
height: hole.rect_pad_height + margin * 2,
|
|
650
|
+
fill: positiveMarginColor,
|
|
651
|
+
realToCanvasMat,
|
|
652
|
+
borderRadius: (hole.rect_border_radius ?? 0) + margin
|
|
653
|
+
});
|
|
654
|
+
}
|
|
336
655
|
drawRect({
|
|
337
656
|
ctx,
|
|
338
657
|
center: { x: hole.x, y: hole.y },
|
|
339
658
|
width: hole.rect_pad_width,
|
|
340
659
|
height: hole.rect_pad_height,
|
|
341
|
-
fill:
|
|
660
|
+
fill: copperColor,
|
|
342
661
|
realToCanvasMat,
|
|
343
662
|
borderRadius: hole.rect_border_radius ?? 0
|
|
344
663
|
});
|
|
664
|
+
if (hasSoldermask && margin < 0) {
|
|
665
|
+
drawSoldermaskRingForRect(
|
|
666
|
+
ctx,
|
|
667
|
+
{ x: hole.x, y: hole.y },
|
|
668
|
+
hole.rect_pad_width,
|
|
669
|
+
hole.rect_pad_height,
|
|
670
|
+
margin,
|
|
671
|
+
hole.rect_border_radius ?? 0,
|
|
672
|
+
0,
|
|
673
|
+
realToCanvasMat,
|
|
674
|
+
soldermaskRingColor,
|
|
675
|
+
copperColor
|
|
676
|
+
);
|
|
677
|
+
}
|
|
345
678
|
const holeX = hole.x + (hole.hole_offset_x ?? 0);
|
|
346
679
|
const holeY = hole.y + (hole.hole_offset_y ?? 0);
|
|
347
680
|
drawPill({
|
|
@@ -355,16 +688,42 @@ function drawPcbPlatedHole(params) {
|
|
|
355
688
|
return;
|
|
356
689
|
}
|
|
357
690
|
if (hole.shape === "rotated_pill_hole_with_rect_pad") {
|
|
691
|
+
if (hasSoldermask && margin > 0) {
|
|
692
|
+
drawRect({
|
|
693
|
+
ctx,
|
|
694
|
+
center: { x: hole.x, y: hole.y },
|
|
695
|
+
width: hole.rect_pad_width + margin * 2,
|
|
696
|
+
height: hole.rect_pad_height + margin * 2,
|
|
697
|
+
fill: positiveMarginColor,
|
|
698
|
+
realToCanvasMat,
|
|
699
|
+
borderRadius: (hole.rect_border_radius ?? 0) + margin,
|
|
700
|
+
rotation: hole.rect_ccw_rotation
|
|
701
|
+
});
|
|
702
|
+
}
|
|
358
703
|
drawRect({
|
|
359
704
|
ctx,
|
|
360
705
|
center: { x: hole.x, y: hole.y },
|
|
361
706
|
width: hole.rect_pad_width,
|
|
362
707
|
height: hole.rect_pad_height,
|
|
363
|
-
fill:
|
|
708
|
+
fill: copperColor,
|
|
364
709
|
realToCanvasMat,
|
|
365
710
|
borderRadius: hole.rect_border_radius ?? 0,
|
|
366
711
|
rotation: hole.rect_ccw_rotation
|
|
367
712
|
});
|
|
713
|
+
if (hasSoldermask && margin < 0) {
|
|
714
|
+
drawSoldermaskRingForRect(
|
|
715
|
+
ctx,
|
|
716
|
+
{ x: hole.x, y: hole.y },
|
|
717
|
+
hole.rect_pad_width,
|
|
718
|
+
hole.rect_pad_height,
|
|
719
|
+
margin,
|
|
720
|
+
hole.rect_border_radius ?? 0,
|
|
721
|
+
hole.rect_ccw_rotation ?? 0,
|
|
722
|
+
realToCanvasMat,
|
|
723
|
+
soldermaskRingColor,
|
|
724
|
+
copperColor
|
|
725
|
+
);
|
|
726
|
+
}
|
|
368
727
|
const holeX = hole.x + (hole.hole_offset_x ?? 0);
|
|
369
728
|
const holeY = hole.y + (hole.hole_offset_y ?? 0);
|
|
370
729
|
drawPill({
|
|
@@ -388,7 +747,7 @@ function drawPcbPlatedHole(params) {
|
|
|
388
747
|
drawPolygon({
|
|
389
748
|
ctx,
|
|
390
749
|
points: padPoints,
|
|
391
|
-
fill:
|
|
750
|
+
fill: copperColor,
|
|
392
751
|
realToCanvasMat
|
|
393
752
|
});
|
|
394
753
|
}
|
|
@@ -589,217 +948,11 @@ function drawPcbHole(params) {
|
|
|
589
948
|
}
|
|
590
949
|
}
|
|
591
950
|
|
|
592
|
-
// lib/drawer/elements/soldermask-margin.ts
|
|
593
|
-
import { applyToPoint as applyToPoint6 } from "transformation-matrix";
|
|
594
|
-
function drawSoldermaskRingForRect(ctx, center, width, height, margin, borderRadius, rotation, realToCanvasMat, soldermaskColor, padColor) {
|
|
595
|
-
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
596
|
-
const scaledWidth = width * Math.abs(realToCanvasMat.a);
|
|
597
|
-
const scaledHeight = height * Math.abs(realToCanvasMat.a);
|
|
598
|
-
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
599
|
-
const scaledRadius = borderRadius * Math.abs(realToCanvasMat.a);
|
|
600
|
-
ctx.save();
|
|
601
|
-
ctx.translate(cx, cy);
|
|
602
|
-
if (rotation !== 0) {
|
|
603
|
-
ctx.rotate(-rotation * (Math.PI / 180));
|
|
604
|
-
}
|
|
605
|
-
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
606
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
607
|
-
ctx.globalCompositeOperation = "source-atop";
|
|
608
|
-
}
|
|
609
|
-
const outerWidth = scaledWidth;
|
|
610
|
-
const outerHeight = scaledHeight;
|
|
611
|
-
const outerRadius = scaledRadius;
|
|
612
|
-
ctx.beginPath();
|
|
613
|
-
if (outerRadius > 0) {
|
|
614
|
-
const x = -outerWidth / 2;
|
|
615
|
-
const y = -outerHeight / 2;
|
|
616
|
-
const r = Math.min(outerRadius, outerWidth / 2, outerHeight / 2);
|
|
617
|
-
ctx.moveTo(x + r, y);
|
|
618
|
-
ctx.lineTo(x + outerWidth - r, y);
|
|
619
|
-
ctx.arcTo(x + outerWidth, y, x + outerWidth, y + r, r);
|
|
620
|
-
ctx.lineTo(x + outerWidth, y + outerHeight - r);
|
|
621
|
-
ctx.arcTo(
|
|
622
|
-
x + outerWidth,
|
|
623
|
-
y + outerHeight,
|
|
624
|
-
x + outerWidth - r,
|
|
625
|
-
y + outerHeight,
|
|
626
|
-
r
|
|
627
|
-
);
|
|
628
|
-
ctx.lineTo(x + r, y + outerHeight);
|
|
629
|
-
ctx.arcTo(x, y + outerHeight, x, y + outerHeight - r, r);
|
|
630
|
-
ctx.lineTo(x, y + r);
|
|
631
|
-
ctx.arcTo(x, y, x + r, y, r);
|
|
632
|
-
} else {
|
|
633
|
-
ctx.rect(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight);
|
|
634
|
-
}
|
|
635
|
-
ctx.fillStyle = soldermaskColor;
|
|
636
|
-
ctx.fill();
|
|
637
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
638
|
-
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
639
|
-
}
|
|
640
|
-
const innerWidth = scaledWidth - scaledMargin * 2;
|
|
641
|
-
const innerHeight = scaledHeight - scaledMargin * 2;
|
|
642
|
-
const innerRadius = Math.max(0, scaledRadius - scaledMargin);
|
|
643
|
-
if (innerWidth > 0 && innerHeight > 0) {
|
|
644
|
-
ctx.beginPath();
|
|
645
|
-
if (innerRadius > 0) {
|
|
646
|
-
const x = -innerWidth / 2;
|
|
647
|
-
const y = -innerHeight / 2;
|
|
648
|
-
const r = Math.min(innerRadius, innerWidth / 2, innerHeight / 2);
|
|
649
|
-
ctx.moveTo(x + r, y);
|
|
650
|
-
ctx.lineTo(x + innerWidth - r, y);
|
|
651
|
-
ctx.arcTo(x + innerWidth, y, x + innerWidth, y + r, r);
|
|
652
|
-
ctx.lineTo(x + innerWidth, y + innerHeight - r);
|
|
653
|
-
ctx.arcTo(
|
|
654
|
-
x + innerWidth,
|
|
655
|
-
y + innerHeight,
|
|
656
|
-
x + innerWidth - r,
|
|
657
|
-
y + innerHeight,
|
|
658
|
-
r
|
|
659
|
-
);
|
|
660
|
-
ctx.lineTo(x + r, y + innerHeight);
|
|
661
|
-
ctx.arcTo(x, y + innerHeight, x, y + innerHeight - r, r);
|
|
662
|
-
ctx.lineTo(x, y + r);
|
|
663
|
-
ctx.arcTo(x, y, x + r, y, r);
|
|
664
|
-
} else {
|
|
665
|
-
ctx.rect(-innerWidth / 2, -innerHeight / 2, innerWidth, innerHeight);
|
|
666
|
-
}
|
|
667
|
-
ctx.fillStyle = padColor;
|
|
668
|
-
ctx.fill();
|
|
669
|
-
}
|
|
670
|
-
ctx.restore();
|
|
671
|
-
}
|
|
672
|
-
function drawSoldermaskRingForCircle(ctx, center, radius, margin, realToCanvasMat, soldermaskColor, padColor) {
|
|
673
|
-
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
674
|
-
const scaledRadius = radius * Math.abs(realToCanvasMat.a);
|
|
675
|
-
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
676
|
-
ctx.save();
|
|
677
|
-
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
678
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
679
|
-
ctx.globalCompositeOperation = "source-atop";
|
|
680
|
-
}
|
|
681
|
-
ctx.beginPath();
|
|
682
|
-
ctx.arc(cx, cy, scaledRadius, 0, Math.PI * 2);
|
|
683
|
-
ctx.fillStyle = soldermaskColor;
|
|
684
|
-
ctx.fill();
|
|
685
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
686
|
-
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
687
|
-
}
|
|
688
|
-
const innerRadius = Math.max(0, scaledRadius - scaledMargin);
|
|
689
|
-
if (innerRadius > 0) {
|
|
690
|
-
ctx.beginPath();
|
|
691
|
-
ctx.arc(cx, cy, innerRadius, 0, Math.PI * 2);
|
|
692
|
-
ctx.fillStyle = padColor;
|
|
693
|
-
ctx.fill();
|
|
694
|
-
}
|
|
695
|
-
ctx.restore();
|
|
696
|
-
}
|
|
697
|
-
function drawSoldermaskRingForPill(ctx, center, width, height, margin, rotation, realToCanvasMat, soldermaskColor, padColor) {
|
|
698
|
-
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
699
|
-
const scaledWidth = width * Math.abs(realToCanvasMat.a);
|
|
700
|
-
const scaledHeight = height * Math.abs(realToCanvasMat.a);
|
|
701
|
-
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
702
|
-
ctx.save();
|
|
703
|
-
ctx.translate(cx, cy);
|
|
704
|
-
if (rotation !== 0) {
|
|
705
|
-
ctx.rotate(-rotation * (Math.PI / 180));
|
|
706
|
-
}
|
|
707
|
-
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
708
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
709
|
-
ctx.globalCompositeOperation = "source-atop";
|
|
710
|
-
}
|
|
711
|
-
const outerWidth = scaledWidth;
|
|
712
|
-
const outerHeight = scaledHeight;
|
|
713
|
-
ctx.beginPath();
|
|
714
|
-
if (outerWidth > outerHeight) {
|
|
715
|
-
const radius = outerHeight / 2;
|
|
716
|
-
const straightLength = outerWidth - outerHeight;
|
|
717
|
-
ctx.moveTo(-straightLength / 2, -radius);
|
|
718
|
-
ctx.lineTo(straightLength / 2, -radius);
|
|
719
|
-
ctx.arc(straightLength / 2, 0, radius, -Math.PI / 2, Math.PI / 2);
|
|
720
|
-
ctx.lineTo(-straightLength / 2, radius);
|
|
721
|
-
ctx.arc(-straightLength / 2, 0, radius, Math.PI / 2, -Math.PI / 2);
|
|
722
|
-
} else if (outerHeight > outerWidth) {
|
|
723
|
-
const radius = outerWidth / 2;
|
|
724
|
-
const straightLength = outerHeight - outerWidth;
|
|
725
|
-
ctx.moveTo(radius, -straightLength / 2);
|
|
726
|
-
ctx.lineTo(radius, straightLength / 2);
|
|
727
|
-
ctx.arc(0, straightLength / 2, radius, 0, Math.PI);
|
|
728
|
-
ctx.lineTo(-radius, -straightLength / 2);
|
|
729
|
-
ctx.arc(0, -straightLength / 2, radius, Math.PI, 0);
|
|
730
|
-
} else {
|
|
731
|
-
ctx.arc(0, 0, outerWidth / 2, 0, Math.PI * 2);
|
|
732
|
-
}
|
|
733
|
-
ctx.fillStyle = soldermaskColor;
|
|
734
|
-
ctx.fill();
|
|
735
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
736
|
-
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
737
|
-
}
|
|
738
|
-
const innerWidth = scaledWidth - scaledMargin * 2;
|
|
739
|
-
const innerHeight = scaledHeight - scaledMargin * 2;
|
|
740
|
-
if (innerWidth > 0 && innerHeight > 0) {
|
|
741
|
-
ctx.beginPath();
|
|
742
|
-
if (innerWidth > innerHeight) {
|
|
743
|
-
const radius = innerHeight / 2;
|
|
744
|
-
const straightLength = innerWidth - innerHeight;
|
|
745
|
-
ctx.moveTo(-straightLength / 2, -radius);
|
|
746
|
-
ctx.lineTo(straightLength / 2, -radius);
|
|
747
|
-
ctx.arc(straightLength / 2, 0, radius, -Math.PI / 2, Math.PI / 2);
|
|
748
|
-
ctx.lineTo(-straightLength / 2, radius);
|
|
749
|
-
ctx.arc(-straightLength / 2, 0, radius, Math.PI / 2, -Math.PI / 2);
|
|
750
|
-
} else if (innerHeight > innerWidth) {
|
|
751
|
-
const radius = innerWidth / 2;
|
|
752
|
-
const straightLength = innerHeight - innerWidth;
|
|
753
|
-
ctx.moveTo(radius, -straightLength / 2);
|
|
754
|
-
ctx.lineTo(radius, straightLength / 2);
|
|
755
|
-
ctx.arc(0, straightLength / 2, radius, 0, Math.PI);
|
|
756
|
-
ctx.lineTo(-radius, -straightLength / 2);
|
|
757
|
-
ctx.arc(0, -straightLength / 2, radius, Math.PI, 0);
|
|
758
|
-
} else {
|
|
759
|
-
ctx.arc(0, 0, innerWidth / 2, 0, Math.PI * 2);
|
|
760
|
-
}
|
|
761
|
-
ctx.fillStyle = padColor;
|
|
762
|
-
ctx.fill();
|
|
763
|
-
}
|
|
764
|
-
ctx.restore();
|
|
765
|
-
}
|
|
766
|
-
function drawSoldermaskRingForOval(ctx, center, radius_x, radius_y, margin, rotation, realToCanvasMat, soldermaskColor, holeColor) {
|
|
767
|
-
const [cx, cy] = applyToPoint6(realToCanvasMat, [center.x, center.y]);
|
|
768
|
-
const scaledRadiusX = radius_x * Math.abs(realToCanvasMat.a);
|
|
769
|
-
const scaledRadiusY = radius_y * Math.abs(realToCanvasMat.a);
|
|
770
|
-
const scaledMargin = Math.abs(margin) * Math.abs(realToCanvasMat.a);
|
|
771
|
-
ctx.save();
|
|
772
|
-
ctx.translate(cx, cy);
|
|
773
|
-
if (rotation !== 0) {
|
|
774
|
-
ctx.rotate(-rotation * (Math.PI / 180));
|
|
775
|
-
}
|
|
776
|
-
const prevCompositeOp = ctx.globalCompositeOperation;
|
|
777
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
778
|
-
ctx.globalCompositeOperation = "source-atop";
|
|
779
|
-
}
|
|
780
|
-
ctx.beginPath();
|
|
781
|
-
ctx.ellipse(0, 0, scaledRadiusX, scaledRadiusY, 0, 0, Math.PI * 2);
|
|
782
|
-
ctx.fillStyle = soldermaskColor;
|
|
783
|
-
ctx.fill();
|
|
784
|
-
if (ctx.globalCompositeOperation !== void 0) {
|
|
785
|
-
ctx.globalCompositeOperation = prevCompositeOp || "source-over";
|
|
786
|
-
}
|
|
787
|
-
const innerRadiusX = Math.max(0, scaledRadiusX - scaledMargin);
|
|
788
|
-
const innerRadiusY = Math.max(0, scaledRadiusY - scaledMargin);
|
|
789
|
-
if (innerRadiusX > 0 && innerRadiusY > 0) {
|
|
790
|
-
ctx.beginPath();
|
|
791
|
-
ctx.ellipse(0, 0, innerRadiusX, innerRadiusY, 0, 0, Math.PI * 2);
|
|
792
|
-
ctx.fillStyle = holeColor;
|
|
793
|
-
ctx.fill();
|
|
794
|
-
}
|
|
795
|
-
ctx.restore();
|
|
796
|
-
}
|
|
797
|
-
|
|
798
951
|
// lib/drawer/elements/pcb-smtpad.ts
|
|
799
952
|
function layerToColor(layer, colorMap) {
|
|
800
953
|
return colorMap.copper[layer] ?? colorMap.copper.top;
|
|
801
954
|
}
|
|
802
|
-
function
|
|
955
|
+
function getSoldermaskColor2(layer, colorMap) {
|
|
803
956
|
return colorMap.soldermaskOverCopper[layer] ?? colorMap.soldermaskOverCopper.top;
|
|
804
957
|
}
|
|
805
958
|
function drawPcbSmtPad(params) {
|
|
@@ -807,7 +960,7 @@ function drawPcbSmtPad(params) {
|
|
|
807
960
|
const color = layerToColor(pad.layer, colorMap);
|
|
808
961
|
const hasSoldermask = pad.is_covered_with_solder_mask === true && pad.soldermask_margin !== void 0 && pad.soldermask_margin !== 0;
|
|
809
962
|
const margin = hasSoldermask ? pad.soldermask_margin : 0;
|
|
810
|
-
const soldermaskRingColor =
|
|
963
|
+
const soldermaskRingColor = getSoldermaskColor2(pad.layer, colorMap);
|
|
811
964
|
const positiveMarginColor = colorMap.substrate;
|
|
812
965
|
if (pad.shape === "rect") {
|
|
813
966
|
if (hasSoldermask && margin > 0) {
|
|
@@ -1766,78 +1919,76 @@ function drawDimensionLine(params) {
|
|
|
1766
1919
|
x: anchor.x + extensionDirection.x * extensionLength,
|
|
1767
1920
|
y: anchor.y + extensionDirection.y * extensionLength
|
|
1768
1921
|
};
|
|
1769
|
-
const
|
|
1922
|
+
const halfWidth = strokeWidth / 2;
|
|
1770
1923
|
const extPerpendicular = {
|
|
1771
1924
|
x: -extensionDirection.y,
|
|
1772
1925
|
y: extensionDirection.x
|
|
1773
1926
|
};
|
|
1774
1927
|
return [
|
|
1775
1928
|
{
|
|
1776
|
-
x: anchor.x + extPerpendicular.x *
|
|
1777
|
-
y: anchor.y + extPerpendicular.y *
|
|
1929
|
+
x: anchor.x + extPerpendicular.x * halfWidth,
|
|
1930
|
+
y: anchor.y + extPerpendicular.y * halfWidth
|
|
1778
1931
|
},
|
|
1779
1932
|
{
|
|
1780
|
-
x: anchor.x - extPerpendicular.x *
|
|
1781
|
-
y: anchor.y - extPerpendicular.y *
|
|
1933
|
+
x: anchor.x - extPerpendicular.x * halfWidth,
|
|
1934
|
+
y: anchor.y - extPerpendicular.y * halfWidth
|
|
1782
1935
|
},
|
|
1783
1936
|
{
|
|
1784
|
-
x: endPoint.x - extPerpendicular.x *
|
|
1785
|
-
y: endPoint.y - extPerpendicular.y *
|
|
1937
|
+
x: endPoint.x - extPerpendicular.x * halfWidth,
|
|
1938
|
+
y: endPoint.y - extPerpendicular.y * halfWidth
|
|
1786
1939
|
},
|
|
1787
1940
|
{
|
|
1788
|
-
x: endPoint.x + extPerpendicular.x *
|
|
1789
|
-
y: endPoint.y + extPerpendicular.y *
|
|
1941
|
+
x: endPoint.x + extPerpendicular.x * halfWidth,
|
|
1942
|
+
y: endPoint.y + extPerpendicular.y * halfWidth
|
|
1790
1943
|
}
|
|
1791
1944
|
];
|
|
1792
1945
|
};
|
|
1793
|
-
|
|
1794
|
-
allPoints.push(
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
allPoints
|
|
1829
|
-
const
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
];
|
|
1840
|
-
allPoints.push(...arrow2, arrow2[0]);
|
|
1946
|
+
allPoints.push(fromOffset);
|
|
1947
|
+
allPoints.push({
|
|
1948
|
+
x: fromBase.x + perpendicular.x * (arrowSize / 2),
|
|
1949
|
+
y: fromBase.y + perpendicular.y * (arrowSize / 2)
|
|
1950
|
+
});
|
|
1951
|
+
allPoints.push({
|
|
1952
|
+
x: fromBase.x + perpendicular.x * (strokeWidth / 2),
|
|
1953
|
+
y: fromBase.y + perpendicular.y * (strokeWidth / 2)
|
|
1954
|
+
});
|
|
1955
|
+
allPoints.push({
|
|
1956
|
+
x: toBase.x + perpendicular.x * (strokeWidth / 2),
|
|
1957
|
+
y: toBase.y + perpendicular.y * (strokeWidth / 2)
|
|
1958
|
+
});
|
|
1959
|
+
allPoints.push({
|
|
1960
|
+
x: toBase.x + perpendicular.x * (arrowSize / 2),
|
|
1961
|
+
y: toBase.y + perpendicular.y * (arrowSize / 2)
|
|
1962
|
+
});
|
|
1963
|
+
allPoints.push(toOffset);
|
|
1964
|
+
allPoints.push({
|
|
1965
|
+
x: toBase.x - perpendicular.x * (arrowSize / 2),
|
|
1966
|
+
y: toBase.y - perpendicular.y * (arrowSize / 2)
|
|
1967
|
+
});
|
|
1968
|
+
allPoints.push({
|
|
1969
|
+
x: toBase.x - perpendicular.x * (strokeWidth / 2),
|
|
1970
|
+
y: toBase.y - perpendicular.y * (strokeWidth / 2)
|
|
1971
|
+
});
|
|
1972
|
+
allPoints.push({
|
|
1973
|
+
x: fromBase.x - perpendicular.x * (strokeWidth / 2),
|
|
1974
|
+
y: fromBase.y - perpendicular.y * (strokeWidth / 2)
|
|
1975
|
+
});
|
|
1976
|
+
allPoints.push({
|
|
1977
|
+
x: fromBase.x - perpendicular.x * (arrowSize / 2),
|
|
1978
|
+
y: fromBase.y - perpendicular.y * (arrowSize / 2)
|
|
1979
|
+
});
|
|
1980
|
+
allPoints.push(fromOffset);
|
|
1981
|
+
const startPoint = allPoints[0];
|
|
1982
|
+
const addTick = (anchor) => {
|
|
1983
|
+
const pts = getExtensionPoints(anchor);
|
|
1984
|
+
allPoints.push(startPoint);
|
|
1985
|
+
allPoints.push(pts[0]);
|
|
1986
|
+
allPoints.push(...pts);
|
|
1987
|
+
allPoints.push(pts[0]);
|
|
1988
|
+
allPoints.push(startPoint);
|
|
1989
|
+
};
|
|
1990
|
+
addTick(from);
|
|
1991
|
+
addTick(to);
|
|
1841
1992
|
drawPolygon({
|
|
1842
1993
|
ctx,
|
|
1843
1994
|
points: allPoints,
|
|
@@ -1873,9 +2024,9 @@ function drawDimensionLine(params) {
|
|
|
1873
2024
|
const rotationRad = textRotation * Math.PI / 180;
|
|
1874
2025
|
const sinRot = Math.abs(Math.sin(rotationRad));
|
|
1875
2026
|
const cosRot = Math.abs(Math.cos(rotationRad));
|
|
1876
|
-
const
|
|
2027
|
+
const halfWidth = textWidth / 2;
|
|
1877
2028
|
const halfHeight = textHeight / 2;
|
|
1878
|
-
const maxExtension =
|
|
2029
|
+
const maxExtension = halfWidth * sinRot + halfHeight * cosRot;
|
|
1879
2030
|
additionalOffset = maxExtension + fontSize * TEXT_INTERSECTION_PADDING_MULTIPLIER;
|
|
1880
2031
|
}
|
|
1881
2032
|
const textOffset = arrowSize * TEXT_OFFSET_MULTIPLIER + additionalOffset;
|
|
@@ -2039,8 +2190,11 @@ var CircuitToCanvasDrawer = class {
|
|
|
2039
2190
|
const hasSoldermaskHoles = elements.some(
|
|
2040
2191
|
(el) => el.type === "pcb_hole" && el.is_covered_with_solder_mask === true
|
|
2041
2192
|
);
|
|
2193
|
+
const hasSoldermaskPlatedHoles = elements.some(
|
|
2194
|
+
(el) => el.type === "pcb_plated_hole" && el.is_covered_with_solder_mask === true
|
|
2195
|
+
);
|
|
2042
2196
|
for (const element of elements) {
|
|
2043
|
-
if (element.type === "pcb_board" && (hasSoldermaskPads || hasSoldermaskHoles)) {
|
|
2197
|
+
if (element.type === "pcb_board" && (hasSoldermaskPads || hasSoldermaskHoles || hasSoldermaskPlatedHoles)) {
|
|
2044
2198
|
this.drawBoardWithSoldermask(element);
|
|
2045
2199
|
} else {
|
|
2046
2200
|
this.drawElement(element, options);
|