altium-toolkit 1.0.2 → 1.0.8

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.
@@ -15,7 +15,7 @@ const MINIMUM_NOTE_TEXT_SIZE = 4
15
15
  export class SchematicNoteRenderer {
16
16
  /**
17
17
  * Builds one boxed schematic note/callout with wrapped text rows.
18
- * @param {{ x: number, y: number, color: string, fontSize?: number, fontFamily?: string, fontWeight?: number, cornerX?: number, cornerY?: number, fill?: string, borderColor?: string, isSolid?: boolean, showBorder?: boolean, textMargin?: number, noteLines?: string[] }} text
18
+ * @param {{ x: number, y: number, color: string, fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, cornerX?: number, cornerY?: number, fill?: string, borderColor?: string, isSolid?: boolean, showBorder?: boolean, textMargin?: number, noteLines?: string[] }} text
19
19
  * @param {number} sheetHeight
20
20
  * @returns {string}
21
21
  */
@@ -52,6 +52,18 @@ export class SchematicNoteRenderer {
52
52
  )
53
53
  const noteStroke = text.showBorder ? borderColor : 'none'
54
54
  const noteSourceLines = text.noteLines || []
55
+ const compactSingleLineNote =
56
+ SchematicNoteRenderer.#isCompactSingleLineNote(
57
+ noteSourceLines,
58
+ height,
59
+ requestedTextSize
60
+ )
61
+ const horizontalTextMargin =
62
+ SchematicNoteRenderer.#resolveHorizontalTextMargin(
63
+ textMargin,
64
+ compactSingleLineNote,
65
+ text
66
+ )
55
67
  const verticalTextMargin =
56
68
  SchematicNoteRenderer.#resolveVerticalTextMargin(
57
69
  textMargin,
@@ -60,14 +72,10 @@ export class SchematicNoteRenderer {
60
72
  )
61
73
  const layout = SchematicNoteRenderer.#resolveTextLayout(
62
74
  noteSourceLines,
63
- Math.max(width - textMargin * 2, requestedTextSize),
75
+ Math.max(width - horizontalTextMargin * 2, requestedTextSize),
64
76
  Math.max(height - verticalTextMargin * 2, requestedTextSize),
65
77
  requestedTextSize,
66
- SchematicNoteRenderer.#isCompactSingleLineNote(
67
- noteSourceLines,
68
- height,
69
- requestedTextSize
70
- )
78
+ compactSingleLineNote
71
79
  )
72
80
  const noteLines = layout.noteLines
73
81
  const textSize = layout.textSize
@@ -80,10 +88,11 @@ export class SchematicNoteRenderer {
80
88
  left,
81
89
  right,
82
90
  top,
83
- textMargin,
91
+ horizontalTextMargin,
84
92
  verticalTextMargin,
85
93
  lineHeight,
86
94
  textSize,
95
+ compactSingleLineNote,
87
96
  text
88
97
  )
89
98
  )
@@ -310,6 +319,25 @@ export class SchematicNoteRenderer {
310
319
  return visibleLineCount === 1 && height <= requestedTextSize * 1.5
311
320
  }
312
321
 
322
+ /**
323
+ * Resolves horizontal text padding for one note box.
324
+ * @param {number} textMargin
325
+ * @param {boolean} compactSingleLineNote
326
+ * @param {{ showBorder?: boolean }} text
327
+ * @returns {number}
328
+ */
329
+ static #resolveHorizontalTextMargin(
330
+ textMargin,
331
+ compactSingleLineNote,
332
+ text
333
+ ) {
334
+ if (compactSingleLineNote && text.showBorder === false) {
335
+ return 0
336
+ }
337
+
338
+ return textMargin
339
+ }
340
+
313
341
  /**
314
342
  * Reduces vertical padding for short note rectangles so readable text is
315
343
  * centered instead of scaled down to satisfy the default margin.
@@ -426,7 +454,8 @@ export class SchematicNoteRenderer {
426
454
  * @param {number} verticalTextMargin
427
455
  * @param {number} lineHeight
428
456
  * @param {number} textSize
429
- * @param {{ color: string, fontFamily?: string, fontWeight?: number }} text
457
+ * @param {boolean} compactSingleLineNote
458
+ * @param {{ color: string, fontFamily?: string, fontWeight?: number, fontStyle?: string }} text
430
459
  * @returns {string}
431
460
  */
432
461
  static #buildNoteLineMarkup(
@@ -439,10 +468,18 @@ export class SchematicNoteRenderer {
439
468
  verticalTextMargin,
440
469
  lineHeight,
441
470
  textSize,
471
+ compactSingleLineNote,
442
472
  text
443
473
  ) {
444
474
  const x = left + horizontalTextMargin
445
- const y = top + verticalTextMargin + textSize + index * lineHeight
475
+ const y =
476
+ top +
477
+ verticalTextMargin +
478
+ SchematicNoteRenderer.#resolveBaselineOffset(
479
+ textSize,
480
+ compactSingleLineNote
481
+ ) +
482
+ index * lineHeight
446
483
 
447
484
  if (/^_+$/.test(String(line || '').trim())) {
448
485
  return (
@@ -483,9 +520,37 @@ export class SchematicNoteRenderer {
483
520
  escapeHtml(text.fontFamily || 'Times New Roman') +
484
521
  '" font-weight="' +
485
522
  formatNumber(text.fontWeight || 400) +
523
+ SchematicNoteRenderer.#buildFontStyleAttribute(text.fontStyle) +
486
524
  '" xml:space="preserve">' +
487
525
  escapeHtml(line) +
488
526
  '</text>'
489
527
  )
490
528
  }
529
+
530
+ /**
531
+ * Builds an optional note font-style attribute.
532
+ * @param {string | undefined} fontStyle
533
+ * @returns {string}
534
+ */
535
+ static #buildFontStyleAttribute(fontStyle) {
536
+ if (!fontStyle || fontStyle === 'normal') {
537
+ return ''
538
+ }
539
+
540
+ return '" font-style="' + escapeHtml(fontStyle)
541
+ }
542
+
543
+ /**
544
+ * Resolves the text baseline offset for a rendered note line.
545
+ * @param {number} textSize
546
+ * @param {boolean} compactSingleLineNote
547
+ * @returns {number}
548
+ */
549
+ static #resolveBaselineOffset(textSize, compactSingleLineNote) {
550
+ if (compactSingleLineNote) {
551
+ return textSize * 0.85
552
+ }
553
+
554
+ return textSize
555
+ }
491
556
  }
@@ -66,7 +66,8 @@ export class SchematicPinSvgRenderer {
66
66
  const defaultNumberX =
67
67
  geometry.bodyX -
68
68
  SchematicPinSvgRenderer.#resolveHorizontalPinNumberClearance(
69
- outerMarkerStyle
69
+ outerMarkerStyle,
70
+ pin
70
71
  )
71
72
  const numberX = hasExplicitOwnerPinName
72
73
  ? SchematicOwnerPinLabelLayout.resolveExplicitOwnerPinNumberX(
@@ -98,7 +99,11 @@ export class SchematicPinSvgRenderer {
98
99
  texts.push(
99
100
  SchematicPinSvgRenderer.#buildPinNameTextMarkup(
100
101
  'schematic-pin-name',
101
- geometry.bodyX + (labelMode === 'name-only' ? 10 : 4),
102
+ geometry.bodyX +
103
+ SchematicPinSvgRenderer.#resolveHorizontalPinNameInset(
104
+ pin,
105
+ labelMode
106
+ ),
102
107
  projectedY + 3,
103
108
  pin,
104
109
  labelColor,
@@ -114,7 +119,8 @@ export class SchematicPinSvgRenderer {
114
119
  const defaultNumberX =
115
120
  geometry.bodyX +
116
121
  SchematicPinSvgRenderer.#resolveHorizontalPinNumberClearance(
117
- outerMarkerStyle
122
+ outerMarkerStyle,
123
+ pin
118
124
  )
119
125
  const numberX = hasExplicitOwnerPinName
120
126
  ? SchematicOwnerPinLabelLayout.resolveExplicitOwnerPinNumberX(
@@ -146,7 +152,11 @@ export class SchematicPinSvgRenderer {
146
152
  texts.push(
147
153
  SchematicPinSvgRenderer.#buildPinNameTextMarkup(
148
154
  'schematic-pin-name',
149
- geometry.bodyX - (labelMode === 'name-only' ? 10 : 4),
155
+ geometry.bodyX -
156
+ SchematicPinSvgRenderer.#resolveHorizontalPinNameInset(
157
+ pin,
158
+ labelMode
159
+ ),
150
160
  projectedY + 3,
151
161
  pin,
152
162
  labelColor,
@@ -363,11 +373,12 @@ export class SchematicPinSvgRenderer {
363
373
  }
364
374
 
365
375
  /**
366
- * Returns the horizontal pin-number clearance needed by an authored marker.
376
+ * Returns the horizontal pin-number clearance needed by the pin geometry.
367
377
  * @param {'single-in' | 'single-out' | 'double' | null} markerStyle
378
+ * @param {{ length?: number }} pin
368
379
  * @returns {number}
369
380
  */
370
- static #resolveHorizontalPinNumberClearance(markerStyle) {
381
+ static #resolveHorizontalPinNumberClearance(markerStyle, pin) {
371
382
  switch (markerStyle) {
372
383
  case 'double':
373
384
  return 17
@@ -375,10 +386,40 @@ export class SchematicPinSvgRenderer {
375
386
  case 'single-out':
376
387
  return 8
377
388
  default:
378
- return 2
389
+ return SchematicPinSvgRenderer.#resolveLongPinInset(pin, 2)
379
390
  }
380
391
  }
381
392
 
393
+ /**
394
+ * Returns the horizontal pin-name inset used inside the symbol body.
395
+ * @param {{ length?: number }} pin
396
+ * @param {'hidden' | 'number-only' | 'name-only' | 'name-and-number'} labelMode
397
+ * @returns {number}
398
+ */
399
+ static #resolveHorizontalPinNameInset(pin, labelMode) {
400
+ if (labelMode === 'name-only') {
401
+ return 10
402
+ }
403
+
404
+ return SchematicPinSvgRenderer.#resolveLongPinInset(pin, 4)
405
+ }
406
+
407
+ /**
408
+ * Adds extra text clearance for long connector-style pin stubs.
409
+ * @param {{ length?: number }} pin
410
+ * @param {number} fallback
411
+ * @returns {number}
412
+ */
413
+ static #resolveLongPinInset(pin, fallback) {
414
+ const length = Math.abs(Number(pin?.length || 0))
415
+
416
+ if (length < 30) {
417
+ return fallback
418
+ }
419
+
420
+ return fallback === 2 ? 10 : 8
421
+ }
422
+
382
423
  /**
383
424
  * Builds one or two authored outer-marker polygons for one horizontal pin.
384
425
  * @param {number} bodyX
@@ -15,7 +15,7 @@ const { createSvgText, escapeHtml, formatNumber, projectSchematicY } =
15
15
  export class SchematicPowerPortRenderer {
16
16
  /**
17
17
  * Renders one power-port symbol and label.
18
- * @param {{ x: number, y: number, text: string, color: string, style?: number, fontSize?: number, fontFamily?: string, fontWeight?: number, anchor?: 'start' | 'middle' | 'end', powerPortDirection?: 'up' | 'down' | 'left' | 'right' }} text
18
+ * @param {{ x: number, y: number, text: string, color: string, style?: number, fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, anchor?: 'start' | 'middle' | 'end', powerPortDirection?: 'up' | 'down' | 'left' | 'right' }} text
19
19
  * @param {{ x1: number, y1: number, x2: number, y2: number }[]} lines
20
20
  * @param {{ x: number, y: number, length: number, orientation: 'left' | 'right' | 'top' | 'bottom' }[]} pins
21
21
  * @param {number} sheetHeight
@@ -32,7 +32,8 @@ export class SchematicPowerPortRenderer {
32
32
  const labelOptions = SchematicTypography.withViewerFontSize({
33
33
  fontSize: Number(text.fontSize || 10),
34
34
  fontFamily: text.fontFamily,
35
- fontWeight: text.fontWeight
35
+ fontWeight: text.fontWeight,
36
+ fontStyle: text.fontStyle
36
37
  })
37
38
  const fontSize = Number(labelOptions.fontSize || 9)
38
39
  const resolvedColor = SchematicColorResolver.resolveColor(
@@ -56,9 +57,7 @@ export class SchematicPowerPortRenderer {
56
57
  y,
57
58
  fontSize,
58
59
  labelOptions,
59
- resolvedColor,
60
- lines,
61
- sheetHeight
60
+ resolvedColor
62
61
  ) +
63
62
  '</g>'
64
63
  )
@@ -66,7 +65,7 @@ export class SchematicPowerPortRenderer {
66
65
 
67
66
  return (
68
67
  '<g class="schematic-power-port schematic-power-port--rail" stroke-linecap="round">' +
69
- SchematicPowerPortRenderer.#buildRailLine(
68
+ SchematicPowerPortRenderer.#buildRailLines(
70
69
  x,
71
70
  y,
72
71
  direction,
@@ -79,9 +78,7 @@ export class SchematicPowerPortRenderer {
79
78
  y,
80
79
  fontSize,
81
80
  labelOptions,
82
- resolvedColor,
83
- lines,
84
- sheetHeight
81
+ resolvedColor
85
82
  ) +
86
83
  '</g>'
87
84
  )
@@ -487,12 +484,18 @@ export class SchematicPowerPortRenderer {
487
484
  * @param {string} color
488
485
  * @returns {string}
489
486
  */
490
- static #buildRailLine(x, y, direction, color) {
487
+ static #buildRailLines(x, y, direction, color) {
491
488
  const stroke = escapeHtml(color)
492
- const x2 =
489
+ const stemX2 =
493
490
  direction === 'left' ? x - 12 : direction === 'right' ? x + 12 : x
494
- const y2 =
491
+ const stemY2 =
495
492
  direction === 'up' ? y - 12 : direction === 'down' ? y + 12 : y
493
+ const capLine = SchematicPowerPortRenderer.#buildRailCapLine(
494
+ stemX2,
495
+ stemY2,
496
+ direction,
497
+ stroke
498
+ )
496
499
 
497
500
  return (
498
501
  '<line x1="' +
@@ -500,6 +503,38 @@ export class SchematicPowerPortRenderer {
500
503
  '" y1="' +
501
504
  formatNumber(y) +
502
505
  '" x2="' +
506
+ formatNumber(stemX2) +
507
+ '" y2="' +
508
+ formatNumber(stemY2) +
509
+ '" stroke="' +
510
+ stroke +
511
+ '" />' +
512
+ capLine
513
+ )
514
+ }
515
+
516
+ /**
517
+ * Builds the perpendicular rail cap at the end of a power-port stem.
518
+ * @param {number} x Stem endpoint x coordinate.
519
+ * @param {number} y Stem endpoint y coordinate.
520
+ * @param {'up' | 'down' | 'left' | 'right'} direction Stem direction.
521
+ * @param {string} stroke Escaped SVG stroke color.
522
+ * @returns {string}
523
+ */
524
+ static #buildRailCapLine(x, y, direction, stroke) {
525
+ const halfLength = 6
526
+ const isVerticalStem = direction === 'up' || direction === 'down'
527
+ const x1 = isVerticalStem ? x - halfLength : x
528
+ const y1 = isVerticalStem ? y : y - halfLength
529
+ const x2 = isVerticalStem ? x + halfLength : x
530
+ const y2 = isVerticalStem ? y : y + halfLength
531
+
532
+ return (
533
+ '<line x1="' +
534
+ formatNumber(x1) +
535
+ '" y1="' +
536
+ formatNumber(y1) +
537
+ '" x2="' +
503
538
  formatNumber(x2) +
504
539
  '" y2="' +
505
540
  formatNumber(y2) +
@@ -516,10 +551,8 @@ export class SchematicPowerPortRenderer {
516
551
  * @param {number} x
517
552
  * @param {number} y
518
553
  * @param {number} fontSize
519
- * @param {{ fontSize?: number, fontFamily?: string, fontWeight?: number }} labelOptions
554
+ * @param {{ fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string }} labelOptions
520
555
  * @param {string} color
521
- * @param {{ x1: number, y1: number, x2: number, y2: number }[]} lines
522
- * @param {number} sheetHeight
523
556
  * @returns {string}
524
557
  */
525
558
  static #buildDirectionalLabel(
@@ -529,18 +562,14 @@ export class SchematicPowerPortRenderer {
529
562
  y,
530
563
  fontSize,
531
564
  labelOptions,
532
- color,
533
- lines = [],
534
- sheetHeight = 0
565
+ color
535
566
  ) {
536
567
  const placement = SchematicPowerPortRenderer.#resolveLabelPlacement(
537
568
  text,
538
569
  direction,
539
570
  x,
540
571
  y,
541
- fontSize,
542
- lines,
543
- sheetHeight
572
+ fontSize
544
573
  )
545
574
 
546
575
  return createSvgText(
@@ -555,38 +584,19 @@ export class SchematicPowerPortRenderer {
555
584
  }
556
585
 
557
586
  /**
558
- * Resolves label placement and avoids nearby horizontal net-line overlap
559
- * for upward rail labels in dense schematic areas.
587
+ * Resolves label placement from the power-port symbol direction.
560
588
  * @param {{ text: string, style?: number }} text
561
589
  * @param {'up' | 'down' | 'left' | 'right'} direction
562
590
  * @param {number} x
563
591
  * @param {number} y
564
592
  * @param {number} fontSize
565
- * @param {{ x1: number, y1: number, x2: number, y2: number }[]} lines
566
- * @param {number} sheetHeight
567
593
  * @returns {{ x: number, y: number, anchor: 'start' | 'middle' | 'end' }}
568
594
  */
569
- static #resolveLabelPlacement(
570
- text,
571
- direction,
572
- x,
573
- y,
574
- fontSize,
575
- lines,
576
- sheetHeight
577
- ) {
595
+ static #resolveLabelPlacement(text, direction, x, y, fontSize) {
578
596
  if (direction === 'up') {
579
597
  return {
580
598
  x,
581
- y: SchematicPowerPortRenderer.#resolveUpwardRailLabelY(
582
- text,
583
- x,
584
- y,
585
- y - 16,
586
- fontSize,
587
- lines,
588
- sheetHeight
589
- ),
599
+ y: y - 14,
590
600
  anchor: 'middle'
591
601
  }
592
602
  }
@@ -601,121 +611,4 @@ export class SchematicPowerPortRenderer {
601
611
 
602
612
  return { x, y: y + 25, anchor: 'middle' }
603
613
  }
604
-
605
- /**
606
- * Shifts an upward rail label below close parallel net lines when the
607
- * default placement would draw text through an existing wire.
608
- * @param {{ text: string, style?: number }} text
609
- * @param {number} x
610
- * @param {number} connectionY
611
- * @param {number} defaultY
612
- * @param {number} fontSize
613
- * @param {{ x1: number, y1: number, x2: number, y2: number }[]} lines
614
- * @param {number} sheetHeight
615
- * @returns {number}
616
- */
617
- static #resolveUpwardRailLabelY(
618
- text,
619
- x,
620
- connectionY,
621
- defaultY,
622
- fontSize,
623
- lines,
624
- sheetHeight
625
- ) {
626
- if (Number(text.style || 0) === 4) {
627
- return defaultY
628
- }
629
-
630
- let labelY = defaultY
631
-
632
- for (const line of lines) {
633
- const horizontalLine =
634
- SchematicPowerPortRenderer.#projectHorizontalLine(
635
- line,
636
- sheetHeight
637
- )
638
-
639
- if (!horizontalLine) {
640
- continue
641
- }
642
-
643
- if (
644
- !SchematicPowerPortRenderer.#horizontalLineIntersectsLabel(
645
- horizontalLine,
646
- text.text,
647
- x,
648
- labelY,
649
- fontSize
650
- )
651
- ) {
652
- continue
653
- }
654
-
655
- labelY = Math.min(
656
- connectionY - 4,
657
- Math.max(labelY, horizontalLine.y + fontSize + 4)
658
- )
659
- }
660
-
661
- return labelY
662
- }
663
-
664
- /**
665
- * Projects one source horizontal line into SVG coordinates.
666
- * @param {{ x1: number, y1: number, x2: number, y2: number }} line
667
- * @param {number} sheetHeight
668
- * @returns {{ y: number, minX: number, maxX: number } | null}
669
- */
670
- static #projectHorizontalLine(line, sheetHeight) {
671
- const y1 = projectSchematicY(sheetHeight, line.y1)
672
- const y2 = projectSchematicY(sheetHeight, line.y2)
673
-
674
- if (Math.abs(y1 - y2) > 0.01) {
675
- return null
676
- }
677
-
678
- return {
679
- y: y1,
680
- minX: Math.min(line.x1, line.x2),
681
- maxX: Math.max(line.x1, line.x2)
682
- }
683
- }
684
-
685
- /**
686
- * Checks whether a projected horizontal line crosses an estimated text box.
687
- * @param {{ y: number, minX: number, maxX: number }} line
688
- * @param {string} label
689
- * @param {number} x
690
- * @param {number} labelY
691
- * @param {number} fontSize
692
- * @returns {boolean}
693
- */
694
- static #horizontalLineIntersectsLabel(line, label, x, labelY, fontSize) {
695
- const textWidth = SchematicPowerPortRenderer.#estimateLabelWidth(
696
- label,
697
- fontSize
698
- )
699
- const textMinX = x - textWidth / 2
700
- const textMaxX = x + textWidth / 2
701
- const textTopY = labelY - fontSize
702
- const textBottomY = labelY + fontSize * 0.25
703
-
704
- return (
705
- line.maxX >= textMinX &&
706
- line.minX <= textMaxX &&
707
- line.y >= textTopY &&
708
- line.y <= textBottomY
709
- )
710
- }
711
-
712
- /**
713
- * Estimates one power-port label width for clearance checks.
714
- * @param {string} label
715
- * @param {number} fontSize
716
- * @returns {number}
717
- */
718
- static #estimateLabelWidth(label, fontSize) {
719
- return String(label || '').length * fontSize * 0.56
720
- }
721
614
  }
@@ -515,6 +515,10 @@ export class SchematicSheetChromeRenderer {
515
515
  SchematicSheetChromeRenderer.#buildSheetValue(titleBlock)
516
516
  const sheetValueHint =
517
517
  SchematicSheetChromeRenderer.#buildSheetValueFooterHint(titleBlock)
518
+ const footerValueOptions =
519
+ SchematicSheetChromeRenderer.#resolveTitleBlockFooterValueOptions(
520
+ titleBlock
521
+ )
518
522
 
519
523
  return (
520
524
  '<g class="sheet-title-block">' +
@@ -702,7 +706,8 @@ export class SchematicSheetChromeRenderer {
702
706
  valueRowY,
703
707
  sheet?.paperSize || 'A4',
704
708
  'var(--schematic-text-color)',
705
- 'middle'
709
+ 'middle',
710
+ footerValueOptions
706
711
  ) +
707
712
  SchematicSheetChromeRenderer.#buildTitleBlockValueMarkup(
708
713
  x + titleBlockWidth * 0.415,
@@ -718,7 +723,8 @@ export class SchematicSheetChromeRenderer {
718
723
  footerDateY,
719
724
  renderedDate,
720
725
  'var(--schematic-text-color)',
721
- 'start'
726
+ 'start',
727
+ footerValueOptions
722
728
  ) +
723
729
  createSvgText(
724
730
  'sheet-title-value',
@@ -726,7 +732,8 @@ export class SchematicSheetChromeRenderer {
726
732
  footerFileY,
727
733
  renderedFileName,
728
734
  'var(--schematic-text-color)',
729
- 'start'
735
+ 'start',
736
+ footerValueOptions
730
737
  ) +
731
738
  createSvgText(
732
739
  'sheet-title-value',
@@ -734,7 +741,8 @@ export class SchematicSheetChromeRenderer {
734
741
  footerFileY,
735
742
  titleBlock.drawnBy || '',
736
743
  'var(--schematic-default-ink-color)',
737
- 'middle'
744
+ 'middle',
745
+ footerValueOptions
738
746
  ) +
739
747
  '</g>'
740
748
  )
@@ -759,8 +767,8 @@ export class SchematicSheetChromeRenderer {
759
767
  /**
760
768
  * Resolves default serif typography for synthesized footer values that do
761
769
  * not have their own recovered hint styling.
762
- * @param {{ footerHints?: Partial<Record<'title' | 'documentNumber' | 'revision', { fontFamily: string }>> }} titleBlock
763
- * @returns {{ fontSize: number, fontFamily: string, fontWeight: number }}
770
+ * @param {{ footerHints?: Partial<Record<'title' | 'documentNumber' | 'revision', { fontFamily: string, fontStyle?: string }>> }} titleBlock
771
+ * @returns {{ fontSize: number, fontFamily: string, fontWeight: number, fontStyle?: string }}
764
772
  */
765
773
  static #resolveTitleBlockFooterValueOptions(titleBlock) {
766
774
  return {
@@ -769,7 +777,10 @@ export class SchematicSheetChromeRenderer {
769
777
  titleBlock?.footerHints?.revision?.fontFamily ||
770
778
  titleBlock?.footerHints?.title?.fontFamily ||
771
779
  'Times New Roman',
772
- fontWeight: 400
780
+ fontWeight: 400,
781
+ fontStyle:
782
+ titleBlock?.footerHints?.revision?.fontStyle ||
783
+ titleBlock?.footerHints?.title?.fontStyle
773
784
  }
774
785
  }
775
786
 
@@ -779,7 +790,7 @@ export class SchematicSheetChromeRenderer {
779
790
  * @param {number} x
780
791
  * @param {number} y
781
792
  * @param {string} text
782
- * @param {{ fontSize: number, fontFamily: string, fontWeight: number }} options
793
+ * @param {{ fontSize: number, fontFamily: string, fontWeight: number, fontStyle?: string }} options
783
794
  * @returns {string}
784
795
  */
785
796
  static #buildTitleBlockLabelMarkup(x, y, text, options) {
@@ -800,7 +811,7 @@ export class SchematicSheetChromeRenderer {
800
811
  * @param {number} resolvedY
801
812
  * @param {string} text
802
813
  * @param {string} fallbackColor
803
- * @param {{ x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number } | undefined} footerHint
814
+ * @param {{ x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number, fontStyle?: string } | undefined} footerHint
804
815
  * @param {number} sheetHeight
805
816
  * @param {boolean} [preserveHintX=true]
806
817
  * @returns {string}
@@ -838,7 +849,8 @@ export class SchematicSheetChromeRenderer {
838
849
  {
839
850
  fontSize: footerHint.fontSize,
840
851
  fontFamily: footerHint.fontFamily,
841
- fontWeight: footerHint.fontWeight
852
+ fontWeight: footerHint.fontWeight,
853
+ fontStyle: footerHint.fontStyle
842
854
  }
843
855
  )
844
856
  }
@@ -850,7 +862,7 @@ export class SchematicSheetChromeRenderer {
850
862
  * @param {number} fallbackY
851
863
  * @param {string} text
852
864
  * @param {string} fallbackColor
853
- * @param {{ x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number } | undefined} footerHint
865
+ * @param {{ x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number, fontStyle?: string } | undefined} footerHint
854
866
  * @param {number} sheetHeight
855
867
  * @param {boolean} [preserveHintX=true]
856
868
  * @returns {string}
@@ -888,15 +900,16 @@ export class SchematicSheetChromeRenderer {
888
900
  {
889
901
  fontSize: footerHint.fontSize,
890
902
  fontFamily: footerHint.fontFamily,
891
- fontWeight: footerHint.fontWeight
903
+ fontWeight: footerHint.fontWeight,
904
+ fontStyle: footerHint.fontStyle
892
905
  }
893
906
  )
894
907
  }
895
908
 
896
909
  /**
897
910
  * Builds one combined sheet-value hint from the recovered sheet-number row.
898
- * @param {{ footerHints?: Partial<Record<'sheetNumber' | 'sheetTotal', { x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number }>> }} titleBlock
899
- * @returns {{ x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number } | undefined}
911
+ * @param {{ footerHints?: Partial<Record<'sheetNumber' | 'sheetTotal', { x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number, fontStyle?: string }>> }} titleBlock
912
+ * @returns {{ x: number, y: number, color: string, fontSize: number, fontFamily: string, fontWeight: number, fontStyle?: string } | undefined}
900
913
  */
901
914
  static #buildSheetValueFooterHint(titleBlock) {
902
915
  const sheetNumberHint = titleBlock?.footerHints?.sheetNumber
@@ -912,7 +925,8 @@ export class SchematicSheetChromeRenderer {
912
925
  color: sheetNumberHint.color,
913
926
  fontSize: sheetNumberHint.fontSize,
914
927
  fontFamily: sheetNumberHint.fontFamily,
915
- fontWeight: sheetNumberHint.fontWeight
928
+ fontWeight: sheetNumberHint.fontWeight,
929
+ fontStyle: sheetNumberHint.fontStyle
916
930
  }
917
931
  }
918
932