@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.
- package/.eslintrc.json +4 -0
- package/.github/workflows/DesignCoreQA.yml +3 -0
- package/TODO.md +49 -6
- package/core/core/core.js +0 -3
- package/core/designCore.js +1 -1
- package/core/dimensions/alignedDimension.js +12 -11
- package/core/dimensions/angularDimension.js +38 -37
- package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +22 -21
- package/core/dimensions/diametricDimension.js +14 -13
- package/core/dimensions/dimension.js +62 -55
- package/core/dimensions/{baseDimension.js → dimensionBase.js} +73 -107
- package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +15 -14
- package/core/dimensions/radialDimension.js +12 -11
- package/core/dimensions/rotatedDimension.js +20 -19
- package/core/entities/arc.js +123 -156
- package/core/entities/arctext.js +222 -184
- package/core/entities/circle.js +77 -99
- package/core/entities/entity.js +114 -93
- package/core/entities/hatch.js +346 -273
- package/core/entities/insert.js +68 -83
- package/core/entities/line.js +21 -142
- package/core/entities/lwpolyline.js +16 -11
- package/core/entities/point.js +19 -19
- package/core/entities/polyline.js +7 -7
- package/core/entities/{basePolyline.js → polylineBase.js} +47 -299
- package/core/entities/rectangle.js +3 -1
- package/core/entities/solid.js +6 -15
- package/core/entities/text.js +190 -201
- package/core/lib/auxiliary/rubberBand.js +32 -0
- package/core/lib/auxiliary/selectionWindow.js +63 -0
- package/core/lib/auxiliary/snapPoint.js +113 -0
- package/core/lib/auxiliary/trackingLine.js +76 -0
- package/core/lib/boundingBox.js +11 -11
- package/core/lib/canvas.js +232 -168
- package/core/lib/clipboard.js +9 -3
- package/core/lib/colour.js +16 -0
- package/core/lib/commandLine.js +1 -6
- package/core/lib/commandManager.js +18 -8
- package/core/lib/constants.js +28 -0
- package/core/lib/dxf/dxf.js +15 -14
- package/core/lib/dxf/dxfIterator.js +2 -2
- package/core/lib/entityManager.js +33 -26
- package/core/lib/inputManager.js +36 -12
- package/core/lib/intersect.js +25 -0
- package/core/lib/matrix.js +1 -1
- package/core/lib/patterns.js +9 -2
- package/core/lib/plotOptions.js +67 -0
- package/core/lib/polylineUtils.js +75 -0
- package/core/lib/renderers/cairoRenderer.js +371 -0
- package/core/lib/renderers/canvasRenderer.js +315 -0
- package/core/lib/renderers/pdfRenderer.js +366 -0
- package/core/lib/renderers/rendererBase.js +284 -0
- package/core/lib/renderers/svgRenderer.js +343 -0
- package/core/lib/scene.js +28 -6
- package/core/lib/selectionManager.js +20 -20
- package/core/lib/settings.js +4 -2
- package/core/lib/snapping.js +4 -191
- package/core/lib/stateManager.js +30 -1
- package/core/lib/utils.js +26 -7
- package/core/properties/entityProperties.js +104 -0
- package/core/properties/property.js +106 -2
- package/core/properties/propertyManager.js +60 -44
- package/core/tables/block.js +50 -81
- package/core/tables/dimStyle.js +5 -5
- package/core/tables/endblk.js +1 -1
- package/core/tables/layer.js +8 -0
- package/core/tables/ltypeManager.js +1 -1
- package/core/tables/styleManagerBase.js +3 -2
- package/core/tables/tableManagerBase.js +8 -3
- package/core/tables/vport.js +2 -2
- package/core/tools/chamfer.js +117 -143
- package/core/tools/chamferFilletBase.js +138 -37
- package/core/tools/copy.js +11 -11
- package/core/tools/copybase.js +3 -3
- package/core/tools/copyclip.js +3 -3
- package/core/tools/cornerEntity.js +2 -2
- package/core/tools/cutclip.js +3 -3
- package/core/tools/explode.js +7 -7
- package/core/tools/extend.js +138 -25
- package/core/tools/fillet.js +92 -189
- package/core/tools/matchProp.js +3 -12
- package/core/tools/mirror.js +15 -14
- package/core/tools/move.js +8 -8
- package/core/tools/offset.js +31 -33
- package/core/tools/pasteclip.js +1 -1
- package/core/tools/purge.js +10 -10
- package/core/tools/rotate.js +19 -16
- package/core/tools/scale.js +7 -7
- package/core/tools/trim.js +271 -29
- package/core/tools/zoom.js +1 -1
- package/cspell.json +321 -0
- package/jest.config.js +6 -0
- package/package.json +5 -3
- package/test/dimensions/alignedDimension.test.js +17 -10
- package/test/dimensions/angularDimension.test.js +13 -13
- package/test/dimensions/diametricDimension.test.js +15 -15
- package/test/dimensions/dimension.test.js +12 -12
- package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +73 -12
- package/test/dimensions/linearDimensionBase.test.js +62 -0
- package/test/dimensions/radialDimension.test.js +15 -15
- package/test/dimensions/rotatedDimension.test.js +18 -11
- package/test/entities/arc.test.js +83 -86
- package/test/entities/arctext.test.js +184 -57
- package/test/entities/circle.test.js +68 -96
- package/test/entities/entity.test.js +42 -8
- package/test/entities/hatch.test.js +569 -96
- package/test/entities/insert.test.js +99 -4
- package/test/entities/line.test.js +15 -41
- package/test/entities/lwpolyline.test.js +104 -0
- package/test/entities/point.test.js +3 -3
- package/test/entities/polyline.test.js +11 -0
- package/test/entities/{basePolyline.test.js → polylineBase.test.js} +192 -57
- package/test/entities/rectangle.test.js +11 -0
- package/test/entities/solid.test.js +1 -1
- package/test/entities/text.test.js +302 -77
- package/test/integration/exportIntegration.reference.dxf +9 -9
- package/test/integration/exportIntegration.test.js +5 -5
- package/test/integration/intersectionIntegration.test.js +4 -5
- package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
- package/test/integration/pdfRendererIntegration.test.js +61 -0
- package/test/integration/svgRendererIntegration.reference.svg +3343 -0
- package/test/integration/svgRendererIntegration.test.js +61 -0
- package/test/integration/userInputIntegration.reference.dxf +1165 -105
- package/test/integration/userInputIntegration.test.js +239 -132
- package/test/lib/boundingBox.test.js +3 -3
- package/test/lib/canvas.test.js +744 -125
- package/test/lib/constants.test.js +27 -0
- package/test/lib/entityManager.test.js +4 -4
- package/test/lib/inputManager.test.js +81 -20
- package/test/lib/intersect.test.js +83 -0
- package/test/lib/plotOptions.test.js +179 -0
- package/test/lib/rubberBand.test.js +84 -0
- package/test/lib/scene.test.js +9 -9
- package/test/lib/selectionManager.test.js +3 -3
- package/test/lib/settings.test.js +5 -6
- package/test/lib/snapping.test.js +72 -130
- package/test/lib/stateManager.test.js +7 -7
- package/test/lib/utils.test.js +36 -2
- package/test/properties/entityProperties.test.js +132 -0
- package/test/properties/property.test.js +53 -0
- package/test/properties/propertyManager.test.js +25 -25
- package/test/renderers/canvasRenderer.test.js +317 -0
- package/test/renderers/pdfRenderer.test.js +271 -0
- package/test/renderers/rendererBase.test.js +213 -0
- package/test/renderers/svgRenderer.test.js +326 -0
- package/test/tables/block.test.js +92 -13
- package/test/tables/endblk.test.js +2 -2
- package/test/tables/layer.test.js +30 -0
- package/test/tables/layerManager.test.js +2 -2
- package/test/test-helpers/hatchGridRenderer.js +180 -0
- package/test/test-helpers/test-helpers.js +158 -6
- package/test/tools/chamfer.test.js +273 -51
- package/test/tools/chamferFilletBase.test.js +125 -36
- package/test/tools/copy.test.js +8 -8
- package/test/tools/copybase.test.js +2 -2
- package/test/tools/copyclip.test.js +2 -2
- package/test/tools/cornerEntity.test.js +8 -8
- package/test/tools/cutclip.test.js +2 -2
- package/test/tools/erase.test.js +6 -6
- package/test/tools/explode.test.js +5 -5
- package/test/tools/extend.test.js +373 -42
- package/test/tools/fillet.test.js +230 -49
- package/test/tools/matchProp.test.js +11 -11
- package/test/tools/mirror.test.js +39 -39
- package/test/tools/move.test.js +7 -7
- package/test/tools/offset.test.js +222 -55
- package/test/tools/pasteclip.test.js +5 -5
- package/test/tools/purge.test.js +4 -4
- package/test/tools/rotate.test.js +39 -9
- package/test/tools/scale.test.js +33 -33
- package/test/tools/trim.test.js +579 -53
- package/test/tools/zoom.test.js +12 -12
- 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.
|
|
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 = {},
|
|
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 (
|
|
50
|
+
if (selectedEntities) {
|
|
50
51
|
origGetItem = scene.entities.get;
|
|
51
|
-
let
|
|
52
|
+
let selectedEntitiesCallCount = 0;
|
|
52
53
|
scene.entities.get = () => {
|
|
53
|
-
return
|
|
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 (
|
|
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
|
+
|