@design-core/core 0.0.6 → 50.1.0

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.
Files changed (173) hide show
  1. package/.eslintrc.json +4 -0
  2. package/.github/workflows/DesignCoreQA.yml +3 -0
  3. package/TODO.md +49 -6
  4. package/core/core/core.js +0 -3
  5. package/core/designCore.js +1 -1
  6. package/core/dimensions/alignedDimension.js +12 -11
  7. package/core/dimensions/angularDimension.js +38 -37
  8. package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +22 -21
  9. package/core/dimensions/diametricDimension.js +14 -13
  10. package/core/dimensions/dimension.js +62 -55
  11. package/core/dimensions/{baseDimension.js → dimensionBase.js} +73 -107
  12. package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +15 -14
  13. package/core/dimensions/radialDimension.js +12 -11
  14. package/core/dimensions/rotatedDimension.js +20 -19
  15. package/core/entities/arc.js +123 -156
  16. package/core/entities/arctext.js +222 -184
  17. package/core/entities/circle.js +77 -99
  18. package/core/entities/entity.js +114 -93
  19. package/core/entities/hatch.js +346 -273
  20. package/core/entities/insert.js +68 -83
  21. package/core/entities/line.js +21 -142
  22. package/core/entities/lwpolyline.js +16 -11
  23. package/core/entities/point.js +19 -19
  24. package/core/entities/polyline.js +7 -7
  25. package/core/entities/{basePolyline.js → polylineBase.js} +47 -299
  26. package/core/entities/rectangle.js +3 -1
  27. package/core/entities/solid.js +6 -15
  28. package/core/entities/text.js +190 -201
  29. package/core/lib/auxiliary/rubberBand.js +32 -0
  30. package/core/lib/auxiliary/selectionWindow.js +63 -0
  31. package/core/lib/auxiliary/snapPoint.js +113 -0
  32. package/core/lib/auxiliary/trackingLine.js +76 -0
  33. package/core/lib/boundingBox.js +11 -11
  34. package/core/lib/canvas.js +232 -168
  35. package/core/lib/clipboard.js +9 -3
  36. package/core/lib/colour.js +16 -0
  37. package/core/lib/commandLine.js +1 -6
  38. package/core/lib/commandManager.js +18 -8
  39. package/core/lib/constants.js +28 -0
  40. package/core/lib/dxf/dxf.js +15 -14
  41. package/core/lib/dxf/dxfIterator.js +2 -2
  42. package/core/lib/entityManager.js +33 -26
  43. package/core/lib/inputManager.js +36 -12
  44. package/core/lib/intersect.js +25 -0
  45. package/core/lib/matrix.js +1 -1
  46. package/core/lib/patterns.js +9 -2
  47. package/core/lib/plotOptions.js +67 -0
  48. package/core/lib/polylineUtils.js +75 -0
  49. package/core/lib/renderers/cairoRenderer.js +371 -0
  50. package/core/lib/renderers/canvasRenderer.js +315 -0
  51. package/core/lib/renderers/pdfRenderer.js +366 -0
  52. package/core/lib/renderers/rendererBase.js +284 -0
  53. package/core/lib/renderers/svgRenderer.js +343 -0
  54. package/core/lib/scene.js +28 -6
  55. package/core/lib/selectionManager.js +20 -20
  56. package/core/lib/settings.js +4 -2
  57. package/core/lib/snapping.js +4 -191
  58. package/core/lib/stateManager.js +30 -1
  59. package/core/lib/utils.js +26 -7
  60. package/core/properties/entityProperties.js +104 -0
  61. package/core/properties/property.js +106 -2
  62. package/core/properties/propertyManager.js +60 -44
  63. package/core/tables/block.js +50 -81
  64. package/core/tables/dimStyle.js +5 -5
  65. package/core/tables/endblk.js +1 -1
  66. package/core/tables/layer.js +8 -0
  67. package/core/tables/ltypeManager.js +1 -1
  68. package/core/tables/styleManagerBase.js +3 -2
  69. package/core/tables/tableManagerBase.js +8 -3
  70. package/core/tables/vport.js +2 -2
  71. package/core/tools/chamfer.js +117 -143
  72. package/core/tools/chamferFilletBase.js +138 -37
  73. package/core/tools/copy.js +11 -11
  74. package/core/tools/copybase.js +3 -3
  75. package/core/tools/copyclip.js +3 -3
  76. package/core/tools/cornerEntity.js +2 -2
  77. package/core/tools/cutclip.js +3 -3
  78. package/core/tools/explode.js +7 -7
  79. package/core/tools/extend.js +138 -25
  80. package/core/tools/fillet.js +92 -189
  81. package/core/tools/matchProp.js +3 -12
  82. package/core/tools/mirror.js +15 -14
  83. package/core/tools/move.js +8 -8
  84. package/core/tools/offset.js +31 -33
  85. package/core/tools/pasteclip.js +1 -1
  86. package/core/tools/purge.js +10 -10
  87. package/core/tools/rotate.js +19 -16
  88. package/core/tools/scale.js +7 -7
  89. package/core/tools/trim.js +271 -29
  90. package/core/tools/zoom.js +1 -1
  91. package/cspell.json +321 -0
  92. package/jest.config.js +6 -0
  93. package/package.json +5 -3
  94. package/test/dimensions/alignedDimension.test.js +17 -10
  95. package/test/dimensions/angularDimension.test.js +13 -13
  96. package/test/dimensions/diametricDimension.test.js +15 -15
  97. package/test/dimensions/dimension.test.js +12 -12
  98. package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +73 -12
  99. package/test/dimensions/linearDimensionBase.test.js +62 -0
  100. package/test/dimensions/radialDimension.test.js +15 -15
  101. package/test/dimensions/rotatedDimension.test.js +18 -11
  102. package/test/entities/arc.test.js +83 -86
  103. package/test/entities/arctext.test.js +184 -57
  104. package/test/entities/circle.test.js +68 -96
  105. package/test/entities/entity.test.js +42 -8
  106. package/test/entities/hatch.test.js +569 -96
  107. package/test/entities/insert.test.js +99 -4
  108. package/test/entities/line.test.js +15 -41
  109. package/test/entities/lwpolyline.test.js +104 -0
  110. package/test/entities/point.test.js +3 -3
  111. package/test/entities/polyline.test.js +11 -0
  112. package/test/entities/{basePolyline.test.js → polylineBase.test.js} +192 -57
  113. package/test/entities/rectangle.test.js +11 -0
  114. package/test/entities/solid.test.js +1 -1
  115. package/test/entities/text.test.js +302 -77
  116. package/test/integration/exportIntegration.reference.dxf +9 -9
  117. package/test/integration/exportIntegration.test.js +5 -5
  118. package/test/integration/intersectionIntegration.test.js +4 -5
  119. package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
  120. package/test/integration/pdfRendererIntegration.test.js +61 -0
  121. package/test/integration/svgRendererIntegration.reference.svg +3343 -0
  122. package/test/integration/svgRendererIntegration.test.js +61 -0
  123. package/test/integration/userInputIntegration.reference.dxf +1165 -105
  124. package/test/integration/userInputIntegration.test.js +239 -132
  125. package/test/lib/boundingBox.test.js +3 -3
  126. package/test/lib/canvas.test.js +744 -125
  127. package/test/lib/constants.test.js +27 -0
  128. package/test/lib/entityManager.test.js +4 -4
  129. package/test/lib/inputManager.test.js +81 -20
  130. package/test/lib/intersect.test.js +83 -0
  131. package/test/lib/plotOptions.test.js +179 -0
  132. package/test/lib/rubberBand.test.js +84 -0
  133. package/test/lib/scene.test.js +9 -9
  134. package/test/lib/selectionManager.test.js +3 -3
  135. package/test/lib/settings.test.js +5 -6
  136. package/test/lib/snapping.test.js +72 -130
  137. package/test/lib/stateManager.test.js +7 -7
  138. package/test/lib/utils.test.js +36 -2
  139. package/test/properties/entityProperties.test.js +132 -0
  140. package/test/properties/property.test.js +53 -0
  141. package/test/properties/propertyManager.test.js +25 -25
  142. package/test/renderers/canvasRenderer.test.js +317 -0
  143. package/test/renderers/pdfRenderer.test.js +271 -0
  144. package/test/renderers/rendererBase.test.js +213 -0
  145. package/test/renderers/svgRenderer.test.js +326 -0
  146. package/test/tables/block.test.js +92 -13
  147. package/test/tables/endblk.test.js +2 -2
  148. package/test/tables/layer.test.js +30 -0
  149. package/test/tables/layerManager.test.js +2 -2
  150. package/test/test-helpers/hatchGridRenderer.js +180 -0
  151. package/test/test-helpers/test-helpers.js +158 -6
  152. package/test/tools/chamfer.test.js +273 -51
  153. package/test/tools/chamferFilletBase.test.js +125 -36
  154. package/test/tools/copy.test.js +8 -8
  155. package/test/tools/copybase.test.js +2 -2
  156. package/test/tools/copyclip.test.js +2 -2
  157. package/test/tools/cornerEntity.test.js +8 -8
  158. package/test/tools/cutclip.test.js +2 -2
  159. package/test/tools/erase.test.js +6 -6
  160. package/test/tools/explode.test.js +5 -5
  161. package/test/tools/extend.test.js +373 -42
  162. package/test/tools/fillet.test.js +230 -49
  163. package/test/tools/matchProp.test.js +11 -11
  164. package/test/tools/mirror.test.js +39 -39
  165. package/test/tools/move.test.js +7 -7
  166. package/test/tools/offset.test.js +222 -55
  167. package/test/tools/pasteclip.test.js +5 -5
  168. package/test/tools/purge.test.js +4 -4
  169. package/test/tools/rotate.test.js +39 -9
  170. package/test/tools/scale.test.js +33 -33
  171. package/test/tools/trim.test.js +579 -53
  172. package/test/tools/zoom.test.js +12 -12
  173. package/core/lib/selectionWindow.js +0 -83
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Shared hatch pattern grid renderer.
3
+ *
4
+ * Draws a full hatch-pattern reference sheet onto any RendererBase-compatible
5
+ * renderer: a 10-column grid of all 82 hatch patterns (alternating square and
6
+ * circle boundaries), pattern name labels, a 5 mm border rectangle, and a
7
+ * title. Used by both the PDF and SVG integration tests so the visual output
8
+ * stays identical across renderer implementations.
9
+ *
10
+ * Usage:
11
+ * const renderer = new SomeRenderer(PAGE_W, PAGE_H);
12
+ * buildHatchGrid(renderer);
13
+ * const output = renderer.getOutput();
14
+ */
15
+
16
+ import { Core } from '../../core/core/core.js';
17
+ import { Hatch } from '../../core/entities/hatch.js';
18
+ import { PolylineBase } from '../../core/entities/polylineBase.js';
19
+ import { Point } from '../../core/entities/point.js';
20
+ import { Text } from '../../core/entities/text.js';
21
+
22
+ // ─── Page & grid constants ────────────────────────────────────────────────────
23
+
24
+ export const PAGE_W = 1190; // landscape A3
25
+ export const PAGE_H = 842;
26
+ export const MARGIN = 5 * 72 / 25.4; // 5 mm in points ≈ 14.17
27
+
28
+ export const COLS = 10;
29
+ export const CELL_W = 115;
30
+ export const CELL_H = 85;
31
+ export const SHAPE_R = 32; // half-side of square / radius of circle (64 pt total)
32
+ export const LABEL_FONT = 6;
33
+ export const TITLE_FONT = 14;
34
+
35
+ // ─── All hatch patterns ───────────────────────────────────────────────────────
36
+
37
+ export const PATTERNS = [
38
+ 'SOLID',
39
+ 'ANGLE', 'ANSI31', 'ANSI32', 'ANSI33', 'ANSI34', 'ANSI35', 'ANSI36', 'ANSI37', 'ANSI38',
40
+ 'AR-B816', 'AR-B816C', 'AR-B88', 'AR-BRELM', 'AR-BRSTD', 'AR-CONC',
41
+ 'AR-HBONE', 'AR-PARQ1', 'AR-RROOF', 'AR-RSHKE', 'AR-SAND',
42
+ 'BOX', 'BRASS', 'BRICK', 'BRSTONE', 'CLAY', 'CORK', 'CROSS',
43
+ 'DASH', 'DOLMIT', 'DOTS', 'EARTH', 'ESCHER', 'FLEX',
44
+ 'GOST_GLASS', 'GOST_WOOD', 'GOST_GROUND', 'GRASS', 'GRATE', 'GRAVEL',
45
+ 'HEX', 'HONEY', 'HOUND', 'INSUL',
46
+ 'ACAD_ISO02W100', 'ACAD_ISO03W100', 'ACAD_ISO04W100', 'ACAD_ISO05W100',
47
+ 'ACAD_ISO06W100', 'ACAD_ISO07W100', 'ACAD_ISO08W100', 'ACAD_ISO09W100',
48
+ 'ACAD_ISO10W100', 'ACAD_ISO11W100', 'ACAD_ISO12W100', 'ACAD_ISO13W100',
49
+ 'ACAD_ISO14W100', 'ACAD_ISO15W100',
50
+ 'JIS_LC_20', 'JIS_LC_20A', 'JIS_LC_8', 'JIS_LC_8A',
51
+ 'JIS_RC_10', 'JIS_RC_15', 'JIS_RC_18', 'JIS_RC_30', 'JIS_STN_1E', 'JIS_WOOD',
52
+ 'LINE', 'MUDST', 'NET', 'NET3', 'PLAST', 'PLASTI',
53
+ 'SACNCR', 'SQUARE', 'STARS', 'STEEL', 'SWAMP', 'TRANS', 'TRIANG', 'ZIGZAG',
54
+ ];
55
+
56
+ // ─── Private helpers ──────────────────────────────────────────────────────────
57
+
58
+ /**
59
+ * Return n evenly-spaced {x, y} points around a circle.
60
+ * Used to draw a visible circle outline via straight-line segments
61
+ * (renderers that lack native arc support use chord approximation).
62
+ *
63
+ * @param {number} cx
64
+ * @param {number} cy
65
+ * @param {number} r
66
+ * @param {number} [n=32]
67
+ * @return {{x: number, y: number}[]}
68
+ */
69
+ function circleOutlinePoints(cx, cy, r, n = 32) {
70
+ const pts = [];
71
+ for (let k = 0; k < n; k++) {
72
+ const a = (k / n) * 2 * Math.PI;
73
+ pts.push({ x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) });
74
+ }
75
+ return pts;
76
+ }
77
+
78
+ // ─── Public API ───────────────────────────────────────────────────────────────
79
+
80
+ /**
81
+ * Draw the hatch pattern reference sheet onto `renderer`.
82
+ *
83
+ * Sets up an identity transform then draws:
84
+ * - A 5 mm border rectangle
85
+ * - A "Hatch Pattern Reference" title
86
+ * - A 10-column grid of all 82 hatch patterns, alternating square and circle
87
+ * boundaries, with pattern name labels beneath each shape
88
+ *
89
+ * `new Core()` is called internally because Hatch.draw() requires
90
+ * DesignCore.Scene.selectionManager to be present.
91
+ *
92
+ * @param {object} renderer
93
+ */
94
+ export function buildHatchGrid(renderer) {
95
+ // Required so that Hatch.draw() can access DesignCore.Scene.selectionManager
96
+ new Core();
97
+
98
+ // Identity transform — draw directly in page coordinates (Y-up, 1 unit = 1 pt)
99
+ renderer.setTransform({ a: 1, d: 1, e: 0, f: 0 });
100
+
101
+ // Border rectangle inset 5 mm from each edge
102
+ renderer.setColour({ r: 0, g: 0, b: 0 });
103
+ renderer.setLineWidth(1);
104
+ renderer.setDash([], 0);
105
+ renderer.drawShape([
106
+ { x: MARGIN, y: MARGIN },
107
+ { x: PAGE_W - MARGIN, y: MARGIN },
108
+ { x: PAGE_W - MARGIN, y: PAGE_H - MARGIN },
109
+ { x: MARGIN, y: PAGE_H - MARGIN },
110
+ ], { closed: true, stroke: true });
111
+
112
+ // Title
113
+ const title = 'Hatch Pattern Reference';
114
+ const titleX = PAGE_W / 2 - Text.getApproximateWidth(title, TITLE_FONT) / 2;
115
+ const titleY = PAGE_H - MARGIN - TITLE_FONT - 2;
116
+ renderer.setColour({ r: 0, g: 0, b: 0 });
117
+ renderer.setLineWidth(0.5);
118
+ renderer.drawText([{ char: title, x: titleX, y: titleY, rotation: 0 }], 'Helvetica', TITLE_FONT);
119
+
120
+ // Grid — centred horizontally, starting below the title
121
+ const xGrid = (PAGE_W - COLS * CELL_W) / 2;
122
+ const yGridTop = titleY - TITLE_FONT - 8;
123
+
124
+ PATTERNS.forEach((name, i) => {
125
+ const row = Math.floor(i / COLS);
126
+ const col = i % COLS;
127
+ const cellX = xGrid + col * CELL_W;
128
+ const cellYTop = yGridTop - row * CELL_H;
129
+
130
+ // Shape centre: 4 pt top padding + SHAPE_R inside the cell
131
+ const cx = cellX + CELL_W / 2;
132
+ const cy = cellYTop - 4 - SHAPE_R;
133
+
134
+ // Alternate square (even index) and circle (odd index) boundaries
135
+ let hatchBoundary;
136
+ let outlinePoints;
137
+
138
+ if (i % 2 === 0) {
139
+ hatchBoundary = new PolylineBase({ points: [
140
+ new Point(cx - SHAPE_R, cy - SHAPE_R),
141
+ new Point(cx + SHAPE_R, cy - SHAPE_R),
142
+ new Point(cx + SHAPE_R, cy + SHAPE_R),
143
+ new Point(cx - SHAPE_R, cy + SHAPE_R),
144
+ ] });
145
+ outlinePoints = hatchBoundary.toPolylinePoints();
146
+ } else {
147
+ // Two exact semicircle arcs (bulge = 1) for clipping; polygon for visible outline
148
+ hatchBoundary = new PolylineBase({ points: [
149
+ new Point(cx + SHAPE_R, cy, 1),
150
+ new Point(cx - SHAPE_R, cy, 1),
151
+ ] });
152
+ outlinePoints = circleOutlinePoints(cx, cy, SHAPE_R);
153
+ }
154
+
155
+ // AR-* patterns have large inter-line spacing; scale down so lines are visible
156
+ const scale = name.startsWith('AR-') ? 0.1 : 1;
157
+ const hatch = new Hatch({ patternName: name, scale });
158
+ hatch.setProperty('childEntities', [hatchBoundary]);
159
+ hatch.buildPatternCache();
160
+
161
+ // Draw hatch fill
162
+ renderer.setColour({ r: 0, g: 0, b: 0 });
163
+ renderer.setLineWidth(0.25);
164
+ renderer.setDash([], 0);
165
+ hatch.draw(renderer);
166
+
167
+ // Draw boundary outline on top
168
+ renderer.setColour({ r: 0, g: 0, b: 0 });
169
+ renderer.setLineWidth(0.5);
170
+ renderer.setDash([], 0);
171
+ renderer.drawShape(outlinePoints, { closed: true, stroke: true });
172
+
173
+ // Pattern name label, centred below the shape
174
+ const labelY = cellYTop - 4 - SHAPE_R * 2 - LABEL_FONT - 2;
175
+ const labelX = cellX + (CELL_W - Text.getApproximateWidth(name, LABEL_FONT)) / 2;
176
+ renderer.setColour({ r: 60, g: 60, b: 60 });
177
+ renderer.setLineWidth(0.25);
178
+ renderer.drawText([{ char: name, x: labelX, y: labelY, rotation: 0 }], 'Helvetica', LABEL_FONT);
179
+ });
180
+ }
@@ -27,10 +27,10 @@ export class File {
27
27
  * @param {Function} testFn - async function to run with the mock active
28
28
  * @param {object} [options] - optional configuration
29
29
  * @param {object} [options.extraMethods] - additional methods to add to the mock inputManager
30
- * @param {Array} [options.selectedItems] - sequential values returned by entities.get
30
+ * @param {Array} [options.selectedEntities] - sequential values returned by entities.get
31
31
  */
32
32
  export async function withMockInput(scene, inputs, testFn, options = {}) {
33
- const { extraMethods = {}, selectedItems } = options;
33
+ const { extraMethods = {}, selectedEntities } = options;
34
34
  const origInputManager = scene.inputManager;
35
35
  let callCount = 0;
36
36
 
@@ -40,17 +40,18 @@ export async function withMockInput(scene, inputs, testFn, options = {}) {
40
40
  return inputs[callCount++];
41
41
  }
42
42
  },
43
+ actionCommand: () => {},
43
44
  executeCommand: () => {},
44
45
  reset: () => {},
45
46
  ...extraMethods,
46
47
  };
47
48
 
48
49
  let origGetItem;
49
- if (selectedItems) {
50
+ if (selectedEntities) {
50
51
  origGetItem = scene.entities.get;
51
- let selectedItemsCallCount = 0;
52
+ let selectedEntitiesCallCount = 0;
52
53
  scene.entities.get = () => {
53
- return selectedItems[selectedItemsCallCount++];
54
+ return selectedEntities[selectedEntitiesCallCount++];
54
55
  };
55
56
  }
56
57
 
@@ -58,9 +59,160 @@ export async function withMockInput(scene, inputs, testFn, options = {}) {
58
59
  await testFn();
59
60
  } finally {
60
61
  scene.inputManager = origInputManager;
61
- if (selectedItems) {
62
+ if (selectedEntities) {
62
63
  scene.entities.get = origGetItem;
63
64
  }
64
65
  }
65
66
  }
66
67
 
68
+ /**
69
+ * A minimal RendererBase-compatible mock for use in unit tests.
70
+ *
71
+ * Tracks colour, line width and dash state so tests can assert on them.
72
+ * Optionally accepts a spy context object; when provided, `save`, `restore`
73
+ * and `applyTransform` delegate to it so tests can verify save/restore
74
+ * balance and transform calls via the context's own spies.
75
+ *
76
+ * @example
77
+ * const renderer = new MockRenderer();
78
+ * entity.draw(renderer);
79
+ * expect(renderer.strokeStyle).toBe('rgb(255,0,0)');
80
+ *
81
+ * @example
82
+ * const ctx = createSpyContext();
83
+ * const renderer = new MockRenderer(ctx);
84
+ * canvas.paint(ctx, 800, 600);
85
+ * expect(ctx.saveDepth).toBe(0); // all saves balanced
86
+ */
87
+ export class MockRenderer {
88
+ /**
89
+ * @param {object|null} [ctx=null] - optional spy context to delegate save/restore to
90
+ */
91
+ constructor(ctx = null) {
92
+ this._ctx = ctx;
93
+ this.strokeStyle = '';
94
+ this.fillStyle = '';
95
+ this.lineWidth = 0;
96
+ this.dashPattern = null;
97
+ }
98
+
99
+ /** @param {{ r: number, g: number, b: number }} rgb */
100
+ setColour(rgb) {
101
+ this.strokeStyle = `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
102
+ this.fillStyle = this.strokeStyle;
103
+ if (this._ctx) {
104
+ this._ctx.strokeStyle = this.strokeStyle;
105
+ this._ctx.fillStyle = this.fillStyle;
106
+ }
107
+ }
108
+
109
+ /** @param {number} w */
110
+ setLineWidth(w) {
111
+ this.lineWidth = w;
112
+ if (this._ctx) this._ctx.lineWidth = w;
113
+ }
114
+
115
+ /** @param {number[]} pattern */
116
+ setDash(pattern) {
117
+ this.dashPattern = pattern;
118
+ }
119
+
120
+ /** @param {object} matrix */
121
+ setTransform(matrix) {}
122
+
123
+ /** @param {Function} styleTransform */
124
+ setStyle(styleTransform) {
125
+ this._styleTransform = styleTransform;
126
+ }
127
+
128
+ /** @param {{ r: number, g: number, b: number }|null} colour */
129
+ setBackgroundColour(colour) {
130
+ this._backgroundColour = colour;
131
+ }
132
+
133
+ /** @return {{ r: number, g: number, b: number }|null} */
134
+ /**
135
+ * @return {object|null}
136
+ */
137
+ getBackgroundColour() {
138
+ return this._backgroundColour ?? null;
139
+ }
140
+
141
+ /** */
142
+ fillBackground() {}
143
+
144
+ /**
145
+ * @param {Array} points
146
+ * @param {object} [options]
147
+ */
148
+ drawShape(points, options) {}
149
+
150
+ /**
151
+ * @param {Array} characters
152
+ * @param {string} fontName
153
+ * @param {number} height
154
+ */
155
+ drawText(characters, fontName, height) {}
156
+
157
+ /** Save current drawing state. */
158
+ save() {
159
+ if (this._ctx) this._ctx.save();
160
+ }
161
+
162
+ /** Restore previously saved drawing state. */
163
+ restore() {
164
+ if (this._ctx) this._ctx.restore();
165
+ }
166
+
167
+ /**
168
+ * @param {object} [transform]
169
+ * @param {number} [transform.x=0]
170
+ * @param {number} [transform.y=0]
171
+ */
172
+ applyTransform({ x = 0, y = 0 } = {}) {
173
+ if (this._ctx) this._ctx.translate(x, y);
174
+ }
175
+
176
+ /**
177
+ * @param {boolean} [isHighlighted=false]
178
+ * @param {object|null} [colour=null]
179
+ * @param {number} [lineWidthDelta=0]
180
+ */
181
+ setHighlight(isHighlighted = false, colour = null, lineWidthDelta = 0) {
182
+ this.isHighlighted = isHighlighted;
183
+ this.highlightColour = colour;
184
+ this.highlightLineWidthDelta = lineWidthDelta;
185
+ }
186
+
187
+ /** @return {number} */
188
+ measureText() {
189
+ return 0;
190
+ }
191
+
192
+ /** @return {number} */
193
+ measureCharWidth() {
194
+ return 0;
195
+ }
196
+
197
+ /**
198
+ * @param {Array} [segments]
199
+ * @param {Array} [dashes]
200
+ */
201
+ drawSegments(segments, dashes) {}
202
+
203
+ /** @param {Array} [points] */
204
+ tracePath(points) {}
205
+
206
+ /** Start a new path. */
207
+ beginPath() {}
208
+
209
+ /** Stroke the current path. */
210
+ stroke() {}
211
+
212
+ /** Close the current path. */
213
+ closePath() {}
214
+
215
+ /** @param {object} [options] */
216
+ applyPath(options) {}
217
+ }
218
+