js-draw 0.0.10 → 0.1.2
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/CHANGELOG.md +11 -0
- package/dist/bundle.js +1 -1
- package/dist/src/Editor.d.ts +2 -2
- package/dist/src/Editor.js +17 -7
- package/dist/src/EditorImage.d.ts +15 -7
- package/dist/src/EditorImage.js +46 -37
- package/dist/src/Pointer.d.ts +3 -2
- package/dist/src/Pointer.js +12 -3
- package/dist/src/SVGLoader.d.ts +6 -2
- package/dist/src/SVGLoader.js +20 -8
- package/dist/src/Viewport.d.ts +4 -0
- package/dist/src/Viewport.js +51 -0
- package/dist/src/components/AbstractComponent.d.ts +9 -2
- package/dist/src/components/AbstractComponent.js +14 -0
- package/dist/src/components/SVGGlobalAttributesObject.d.ts +1 -1
- package/dist/src/components/SVGGlobalAttributesObject.js +1 -1
- package/dist/src/components/Stroke.d.ts +1 -1
- package/dist/src/components/Stroke.js +1 -1
- package/dist/src/components/UnknownSVGObject.d.ts +1 -1
- package/dist/src/components/UnknownSVGObject.js +1 -1
- package/dist/src/components/builders/ArrowBuilder.d.ts +1 -1
- package/dist/src/components/builders/FreehandLineBuilder.d.ts +1 -1
- package/dist/src/components/builders/FreehandLineBuilder.js +1 -1
- package/dist/src/components/builders/LineBuilder.d.ts +1 -1
- package/dist/src/components/builders/RectangleBuilder.d.ts +1 -1
- package/dist/src/components/builders/types.d.ts +1 -1
- package/dist/src/geometry/Mat33.js +3 -0
- package/dist/src/geometry/Path.d.ts +1 -1
- package/dist/src/geometry/Path.js +102 -69
- package/dist/src/geometry/Rect2.d.ts +1 -0
- package/dist/src/geometry/Rect2.js +47 -9
- package/dist/src/{Display.d.ts → rendering/Display.d.ts} +5 -2
- package/dist/src/{Display.js → rendering/Display.js} +34 -4
- package/dist/src/rendering/caching/CacheRecord.d.ts +19 -0
- package/dist/src/rendering/caching/CacheRecord.js +52 -0
- package/dist/src/rendering/caching/CacheRecordManager.d.ts +11 -0
- package/dist/src/rendering/caching/CacheRecordManager.js +31 -0
- package/dist/src/rendering/caching/RenderingCache.d.ts +12 -0
- package/dist/src/rendering/caching/RenderingCache.js +42 -0
- package/dist/src/rendering/caching/RenderingCacheNode.d.ts +28 -0
- package/dist/src/rendering/caching/RenderingCacheNode.js +301 -0
- package/dist/src/rendering/caching/testUtils.d.ts +9 -0
- package/dist/src/rendering/caching/testUtils.js +20 -0
- package/dist/src/rendering/caching/types.d.ts +21 -0
- package/dist/src/rendering/caching/types.js +1 -0
- package/dist/src/rendering/{AbstractRenderer.d.ts → renderers/AbstractRenderer.d.ts} +20 -9
- package/dist/src/rendering/{AbstractRenderer.js → renderers/AbstractRenderer.js} +37 -3
- package/dist/src/rendering/{CanvasRenderer.d.ts → renderers/CanvasRenderer.d.ts} +10 -5
- package/dist/src/rendering/{CanvasRenderer.js → renderers/CanvasRenderer.js} +60 -20
- package/dist/src/rendering/{DummyRenderer.d.ts → renderers/DummyRenderer.d.ts} +9 -5
- package/dist/src/rendering/{DummyRenderer.js → renderers/DummyRenderer.js} +35 -4
- package/dist/src/rendering/{SVGRenderer.d.ts → renderers/SVGRenderer.d.ts} +7 -5
- package/dist/src/rendering/{SVGRenderer.js → renderers/SVGRenderer.js} +35 -18
- package/dist/src/testing/createEditor.js +1 -1
- package/dist/src/toolbar/HTMLToolbar.d.ts +2 -1
- package/dist/src/toolbar/HTMLToolbar.js +165 -154
- package/dist/src/toolbar/icons.d.ts +10 -0
- package/dist/src/toolbar/icons.js +180 -0
- package/dist/src/toolbar/localization.d.ts +4 -1
- package/dist/src/toolbar/localization.js +4 -1
- package/dist/src/toolbar/types.d.ts +4 -0
- package/dist/src/tools/PanZoom.d.ts +9 -6
- package/dist/src/tools/PanZoom.js +30 -21
- package/dist/src/tools/Pen.js +8 -3
- package/dist/src/tools/SelectionTool.js +9 -24
- package/dist/src/tools/ToolController.d.ts +5 -6
- package/dist/src/tools/ToolController.js +8 -10
- package/dist/src/tools/localization.d.ts +1 -0
- package/dist/src/tools/localization.js +1 -0
- package/dist/src/types.d.ts +2 -1
- package/package.json +1 -1
- package/src/Editor.ts +19 -8
- package/src/EditorImage.test.ts +2 -2
- package/src/EditorImage.ts +58 -42
- package/src/Pointer.ts +13 -4
- package/src/SVGLoader.ts +36 -10
- package/src/Viewport.ts +68 -0
- package/src/components/AbstractComponent.ts +21 -2
- package/src/components/SVGGlobalAttributesObject.ts +2 -2
- package/src/components/Stroke.ts +2 -2
- package/src/components/UnknownSVGObject.ts +2 -2
- package/src/components/builders/ArrowBuilder.ts +1 -1
- package/src/components/builders/FreehandLineBuilder.ts +2 -2
- package/src/components/builders/LineBuilder.ts +1 -1
- package/src/components/builders/RectangleBuilder.ts +1 -1
- package/src/components/builders/types.ts +1 -1
- package/src/geometry/Mat33.ts +3 -0
- package/src/geometry/Path.fromString.test.ts +94 -4
- package/src/geometry/Path.toString.test.ts +12 -2
- package/src/geometry/Path.ts +107 -71
- package/src/geometry/Rect2.test.ts +47 -8
- package/src/geometry/Rect2.ts +57 -9
- package/src/{Display.ts → rendering/Display.ts} +39 -6
- package/src/rendering/caching/CacheRecord.test.ts +49 -0
- package/src/rendering/caching/CacheRecord.ts +73 -0
- package/src/rendering/caching/CacheRecordManager.ts +45 -0
- package/src/rendering/caching/RenderingCache.test.ts +44 -0
- package/src/rendering/caching/RenderingCache.ts +63 -0
- package/src/rendering/caching/RenderingCacheNode.ts +378 -0
- package/src/rendering/caching/testUtils.ts +35 -0
- package/src/rendering/caching/types.ts +39 -0
- package/src/rendering/{AbstractRenderer.ts → renderers/AbstractRenderer.ts} +57 -9
- package/src/rendering/{CanvasRenderer.ts → renderers/CanvasRenderer.ts} +74 -25
- package/src/rendering/renderers/DummyRenderer.test.ts +43 -0
- package/src/rendering/{DummyRenderer.ts → renderers/DummyRenderer.ts} +50 -7
- package/src/rendering/{SVGRenderer.ts → renderers/SVGRenderer.ts} +39 -23
- package/src/testing/createEditor.ts +1 -1
- package/src/toolbar/HTMLToolbar.ts +199 -170
- package/src/toolbar/icons.ts +203 -0
- package/src/toolbar/localization.ts +9 -2
- package/src/toolbar/toolbar.css +21 -8
- package/src/toolbar/types.ts +5 -0
- package/src/tools/PanZoom.ts +37 -27
- package/src/tools/Pen.ts +7 -3
- package/src/tools/SelectionTool.test.ts +1 -1
- package/src/tools/SelectionTool.ts +12 -33
- package/src/tools/ToolController.ts +3 -5
- package/src/tools/localization.ts +2 -0
- package/src/types.ts +10 -3
- package/tsconfig.json +1 -0
- package/dist/__mocks__/coloris.d.ts +0 -2
- package/dist/__mocks__/coloris.js +0 -5
@@ -1,5 +1,5 @@
|
|
1
|
-
import Color4 from '
|
2
|
-
import { Vec2 } from '
|
1
|
+
import Color4 from '../../Color4';
|
2
|
+
import { Vec2 } from '../../geometry/Vec2';
|
3
3
|
import AbstractRenderer from './AbstractRenderer';
|
4
4
|
export default class CanvasRenderer extends AbstractRenderer {
|
5
5
|
constructor(ctx, viewport) {
|
@@ -7,8 +7,29 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
7
7
|
this.ctx = ctx;
|
8
8
|
this.ignoreObjectsAboveLevel = null;
|
9
9
|
this.ignoringObject = false;
|
10
|
+
this.clipLevels = [];
|
10
11
|
this.setDraftMode(false);
|
11
12
|
}
|
13
|
+
canRenderFromWithoutDataLoss(other) {
|
14
|
+
return other instanceof CanvasRenderer;
|
15
|
+
}
|
16
|
+
renderFromOtherOfSameType(transformBy, other) {
|
17
|
+
if (!(other instanceof CanvasRenderer)) {
|
18
|
+
throw new Error(`${other} cannot be rendered onto ${this}`);
|
19
|
+
}
|
20
|
+
transformBy = this.getCanvasToScreenTransform().rightMul(transformBy);
|
21
|
+
this.ctx.save();
|
22
|
+
// From MDN, transform(a,b,c,d,e,f)
|
23
|
+
// takes input such that
|
24
|
+
// ⎡ a c e ⎤
|
25
|
+
// ⎢ b d f ⎥ transforms content drawn to [ctx].
|
26
|
+
// ⎣ 0 0 1 ⎦
|
27
|
+
this.ctx.transform(transformBy.a1, transformBy.b1, // a, b
|
28
|
+
transformBy.a2, transformBy.b2, // c, d
|
29
|
+
transformBy.a3, transformBy.b3);
|
30
|
+
this.ctx.drawImage(other.ctx.canvas, 0, 0);
|
31
|
+
this.ctx.restore();
|
32
|
+
}
|
12
33
|
// Set parameters for lower/higher quality rendering
|
13
34
|
setDraftMode(draftMode) {
|
14
35
|
if (draftMode) {
|
@@ -29,7 +50,7 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
29
50
|
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
30
51
|
}
|
31
52
|
beginPath(startPoint) {
|
32
|
-
startPoint = this.
|
53
|
+
startPoint = this.canvasToScreen(startPoint);
|
33
54
|
this.ctx.beginPath();
|
34
55
|
this.ctx.moveTo(startPoint.x, startPoint.y);
|
35
56
|
}
|
@@ -38,23 +59,23 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
38
59
|
this.ctx.fill();
|
39
60
|
if (style.stroke) {
|
40
61
|
this.ctx.strokeStyle = style.stroke.color.toHexString();
|
41
|
-
this.ctx.lineWidth = this.
|
62
|
+
this.ctx.lineWidth = this.getSizeOfCanvasPixelOnScreen() * style.stroke.width;
|
42
63
|
this.ctx.stroke();
|
43
64
|
}
|
44
65
|
this.ctx.closePath();
|
45
66
|
}
|
46
67
|
lineTo(point) {
|
47
|
-
point = this.
|
68
|
+
point = this.canvasToScreen(point);
|
48
69
|
this.ctx.lineTo(point.x, point.y);
|
49
70
|
}
|
50
71
|
moveTo(point) {
|
51
|
-
point = this.
|
72
|
+
point = this.canvasToScreen(point);
|
52
73
|
this.ctx.moveTo(point.x, point.y);
|
53
74
|
}
|
54
75
|
traceCubicBezierCurve(p1, p2, p3) {
|
55
|
-
p1 = this.
|
56
|
-
p2 = this.
|
57
|
-
p3 = this.
|
76
|
+
p1 = this.canvasToScreen(p1);
|
77
|
+
p2 = this.canvasToScreen(p2);
|
78
|
+
p3 = this.canvasToScreen(p3);
|
58
79
|
// Approximate the curve if small enough.
|
59
80
|
const delta1 = p2.minus(p1);
|
60
81
|
const delta2 = p3.minus(p2);
|
@@ -67,8 +88,8 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
67
88
|
}
|
68
89
|
}
|
69
90
|
traceQuadraticBezierCurve(controlPoint, endPoint) {
|
70
|
-
controlPoint = this.
|
71
|
-
endPoint = this.
|
91
|
+
controlPoint = this.canvasToScreen(controlPoint);
|
92
|
+
endPoint = this.canvasToScreen(endPoint);
|
72
93
|
// Approximate the curve with a line if small enough
|
73
94
|
const delta = controlPoint.minus(endPoint);
|
74
95
|
if (delta.magnitudeSquared() < this.minSquareCurveApproxDist) {
|
@@ -84,20 +105,30 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
84
105
|
}
|
85
106
|
super.drawPath(path);
|
86
107
|
}
|
87
|
-
startObject(boundingBox) {
|
88
|
-
|
89
|
-
const diagonal = this.viewport.canvasToScreenTransform.transformVec3(boundingBox.size);
|
90
|
-
const bothDimenMinSize = this.minRenderSizeBothDimens;
|
91
|
-
const bothTooSmall = Math.abs(diagonal.x) < bothDimenMinSize && Math.abs(diagonal.y) < bothDimenMinSize;
|
92
|
-
const anyDimenMinSize = this.minRenderSizeAnyDimen;
|
93
|
-
const anyTooSmall = Math.abs(diagonal.x) < anyDimenMinSize || Math.abs(diagonal.y) < anyDimenMinSize;
|
94
|
-
if (bothTooSmall || anyTooSmall) {
|
108
|
+
startObject(boundingBox, clip) {
|
109
|
+
if (this.isTooSmallToRender(boundingBox)) {
|
95
110
|
this.ignoreObjectsAboveLevel = this.getNestingLevel();
|
96
111
|
this.ignoringObject = true;
|
97
112
|
}
|
98
113
|
super.startObject(boundingBox);
|
114
|
+
if (!this.ignoringObject && clip) {
|
115
|
+
this.clipLevels.push(this.objectLevel);
|
116
|
+
this.ctx.save();
|
117
|
+
this.ctx.beginPath();
|
118
|
+
for (const corner of boundingBox.corners) {
|
119
|
+
const screenCorner = this.canvasToScreen(corner);
|
120
|
+
this.ctx.lineTo(screenCorner.x, screenCorner.y);
|
121
|
+
}
|
122
|
+
this.ctx.clip();
|
123
|
+
}
|
99
124
|
}
|
100
125
|
endObject() {
|
126
|
+
if (!this.ignoringObject && this.clipLevels.length > 0) {
|
127
|
+
if (this.clipLevels[this.clipLevels.length - 1] === this.objectLevel) {
|
128
|
+
this.ctx.restore();
|
129
|
+
this.clipLevels.pop();
|
130
|
+
}
|
131
|
+
}
|
101
132
|
super.endObject();
|
102
133
|
// If exiting an object with a too-small-to-draw bounding box,
|
103
134
|
if (this.ignoreObjectsAboveLevel !== null && this.getNestingLevel() <= this.ignoreObjectsAboveLevel) {
|
@@ -108,7 +139,7 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
108
139
|
drawPoints(...points) {
|
109
140
|
const pointRadius = 10;
|
110
141
|
for (let i = 0; i < points.length; i++) {
|
111
|
-
const point = this.
|
142
|
+
const point = this.canvasToScreen(points[i]);
|
112
143
|
this.ctx.beginPath();
|
113
144
|
this.ctx.arc(point.x, point.y, pointRadius, 0, Math.PI * 2);
|
114
145
|
this.ctx.fillStyle = Color4.ofRGBA(0.5 + Math.sin(i) / 2, 1.0, 0.5 + Math.cos(i * 0.2) / 4, 0.5).toHexString();
|
@@ -121,4 +152,13 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
121
152
|
this.ctx.fillText(`${i}`, point.x, point.y, pointRadius * 2);
|
122
153
|
}
|
123
154
|
}
|
155
|
+
isTooSmallToRender(rect) {
|
156
|
+
// Should we ignore all objects within this object's bbox?
|
157
|
+
const diagonal = this.getCanvasToScreenTransform().transformVec3(rect.size);
|
158
|
+
const bothDimenMinSize = this.minRenderSizeBothDimens;
|
159
|
+
const bothTooSmall = Math.abs(diagonal.x) < bothDimenMinSize && Math.abs(diagonal.y) < bothDimenMinSize;
|
160
|
+
const anyDimenMinSize = this.minRenderSizeAnyDimen;
|
161
|
+
const anyTooSmall = Math.abs(diagonal.x) < anyDimenMinSize || Math.abs(diagonal.y) < anyDimenMinSize;
|
162
|
+
return bothTooSmall || anyTooSmall;
|
163
|
+
}
|
124
164
|
}
|
@@ -1,7 +1,8 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import
|
4
|
-
import
|
1
|
+
import Mat33 from '../../geometry/Mat33';
|
2
|
+
import Rect2 from '../../geometry/Rect2';
|
3
|
+
import { Point2, Vec2 } from '../../geometry/Vec2';
|
4
|
+
import Vec3 from '../../geometry/Vec3';
|
5
|
+
import Viewport from '../../Viewport';
|
5
6
|
import AbstractRenderer, { RenderingStyle } from './AbstractRenderer';
|
6
7
|
export default class DummyRenderer extends AbstractRenderer {
|
7
8
|
clearedCount: number;
|
@@ -20,6 +21,9 @@ export default class DummyRenderer extends AbstractRenderer {
|
|
20
21
|
protected traceCubicBezierCurve(p1: Vec3, p2: Vec3, p3: Vec3): void;
|
21
22
|
protected traceQuadraticBezierCurve(controlPoint: Vec3, endPoint: Vec3): void;
|
22
23
|
drawPoints(..._points: Vec3[]): void;
|
23
|
-
startObject(boundingBox: Rect2): void;
|
24
|
+
startObject(boundingBox: Rect2, _clip: boolean): void;
|
24
25
|
endObject(): void;
|
26
|
+
isTooSmallToRender(_rect: Rect2): boolean;
|
27
|
+
canRenderFromWithoutDataLoss(other: AbstractRenderer): boolean;
|
28
|
+
renderFromOtherOfSameType(transform: Mat33, other: AbstractRenderer): void;
|
25
29
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
// Renderer that outputs nothing. Useful for automated tests.
|
2
|
-
import { Vec2 } from '
|
2
|
+
import { Vec2 } from '../../geometry/Vec2';
|
3
3
|
import AbstractRenderer from './AbstractRenderer';
|
4
4
|
export default class DummyRenderer extends AbstractRenderer {
|
5
5
|
constructor(viewport) {
|
@@ -14,8 +14,15 @@ export default class DummyRenderer extends AbstractRenderer {
|
|
14
14
|
this.pointBuffer = [];
|
15
15
|
}
|
16
16
|
displaySize() {
|
17
|
-
//
|
18
|
-
|
17
|
+
// Do we have a stored viewport size?
|
18
|
+
const viewportSize = this.getViewport().getResolution();
|
19
|
+
// Don't use a 0x0 viewport — DummyRenderer is often used
|
20
|
+
// for tests that run without a display, so pretend we have a
|
21
|
+
// reasonable-sized display.
|
22
|
+
if (viewportSize.x === 0 || viewportSize.y === 0) {
|
23
|
+
return Vec2.of(640, 480);
|
24
|
+
}
|
25
|
+
return viewportSize;
|
19
26
|
}
|
20
27
|
clear() {
|
21
28
|
this.clearedCount++;
|
@@ -35,18 +42,25 @@ export default class DummyRenderer extends AbstractRenderer {
|
|
35
42
|
this.lastFillStyle = style;
|
36
43
|
}
|
37
44
|
lineTo(point) {
|
45
|
+
point = this.canvasToScreen(point);
|
38
46
|
this.lastPoint = point;
|
39
47
|
this.pointBuffer.push(point);
|
40
48
|
}
|
41
49
|
moveTo(point) {
|
50
|
+
point = this.canvasToScreen(point);
|
42
51
|
this.lastPoint = point;
|
43
52
|
this.pointBuffer.push(point);
|
44
53
|
}
|
45
54
|
traceCubicBezierCurve(p1, p2, p3) {
|
55
|
+
p1 = this.canvasToScreen(p1);
|
56
|
+
p2 = this.canvasToScreen(p2);
|
57
|
+
p3 = this.canvasToScreen(p3);
|
46
58
|
this.lastPoint = p3;
|
47
59
|
this.pointBuffer.push(p1, p2, p3);
|
48
60
|
}
|
49
61
|
traceQuadraticBezierCurve(controlPoint, endPoint) {
|
62
|
+
controlPoint = this.canvasToScreen(controlPoint);
|
63
|
+
endPoint = this.canvasToScreen(endPoint);
|
50
64
|
this.lastPoint = endPoint;
|
51
65
|
this.pointBuffer.push(controlPoint, endPoint);
|
52
66
|
}
|
@@ -54,7 +68,7 @@ export default class DummyRenderer extends AbstractRenderer {
|
|
54
68
|
// drawPoints is intended for debugging.
|
55
69
|
// As such, it is unlikely to be the target of automated tests.
|
56
70
|
}
|
57
|
-
startObject(boundingBox) {
|
71
|
+
startObject(boundingBox, _clip) {
|
58
72
|
super.startObject(boundingBox);
|
59
73
|
this.objectNestingLevel += 1;
|
60
74
|
}
|
@@ -62,4 +76,21 @@ export default class DummyRenderer extends AbstractRenderer {
|
|
62
76
|
super.endObject();
|
63
77
|
this.objectNestingLevel -= 1;
|
64
78
|
}
|
79
|
+
isTooSmallToRender(_rect) {
|
80
|
+
return false;
|
81
|
+
}
|
82
|
+
canRenderFromWithoutDataLoss(other) {
|
83
|
+
return other instanceof DummyRenderer;
|
84
|
+
}
|
85
|
+
renderFromOtherOfSameType(transform, other) {
|
86
|
+
if (!(other instanceof DummyRenderer)) {
|
87
|
+
throw new Error(`${other} cannot be rendered onto ${this}`);
|
88
|
+
}
|
89
|
+
this.renderedPathCount += other.renderedPathCount;
|
90
|
+
this.lastFillStyle = other.lastFillStyle;
|
91
|
+
this.lastPoint = other.lastPoint;
|
92
|
+
this.pointBuffer.push(...other.pointBuffer.map(point => {
|
93
|
+
return transform.transformVec2(point);
|
94
|
+
}));
|
95
|
+
}
|
65
96
|
}
|
@@ -1,6 +1,7 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import
|
1
|
+
import { LoadSaveDataTable } from '../../components/AbstractComponent';
|
2
|
+
import Rect2 from '../../geometry/Rect2';
|
3
|
+
import { Point2, Vec2 } from '../../geometry/Vec2';
|
4
|
+
import Viewport from '../../Viewport';
|
4
5
|
import AbstractRenderer, { RenderingStyle } from './AbstractRenderer';
|
5
6
|
export default class SVGRenderer extends AbstractRenderer {
|
6
7
|
private elem;
|
@@ -9,7 +10,7 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
9
10
|
private lastPathStyle;
|
10
11
|
private lastPath;
|
11
12
|
private lastPathStart;
|
12
|
-
private
|
13
|
+
private objectElems;
|
13
14
|
private overwrittenAttrs;
|
14
15
|
constructor(elem: SVGSVGElement, viewport: Viewport);
|
15
16
|
setRootSVGAttribute(name: string, value: string | null): void;
|
@@ -19,11 +20,12 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
19
20
|
protected endPath(style: RenderingStyle): void;
|
20
21
|
private addPathToSVG;
|
21
22
|
startObject(boundingBox: Rect2): void;
|
22
|
-
endObject(): void;
|
23
|
+
endObject(loaderData?: LoadSaveDataTable): void;
|
23
24
|
protected lineTo(point: Point2): void;
|
24
25
|
protected moveTo(point: Point2): void;
|
25
26
|
protected traceCubicBezierCurve(controlPoint1: Point2, controlPoint2: Point2, endPoint: Point2): void;
|
26
27
|
protected traceQuadraticBezierCurve(controlPoint: Point2, endPoint: Point2): void;
|
27
28
|
drawPoints(...points: Point2[]): void;
|
28
29
|
drawSVGElem(elem: SVGElement): void;
|
30
|
+
isTooSmallToRender(_rect: Rect2): boolean;
|
29
31
|
}
|
@@ -1,11 +1,13 @@
|
|
1
|
-
import Path, { PathCommandType } from '
|
2
|
-
import { Vec2 } from '
|
1
|
+
import Path, { PathCommandType } from '../../geometry/Path';
|
2
|
+
import { Vec2 } from '../../geometry/Vec2';
|
3
|
+
import { svgAttributesDataKey } from '../../SVGLoader';
|
3
4
|
import AbstractRenderer from './AbstractRenderer';
|
4
5
|
const svgNameSpace = 'http://www.w3.org/2000/svg';
|
5
6
|
export default class SVGRenderer extends AbstractRenderer {
|
6
7
|
constructor(elem, viewport) {
|
7
8
|
super(viewport);
|
8
9
|
this.elem = elem;
|
10
|
+
this.objectElems = null;
|
9
11
|
this.overwrittenAttrs = {};
|
10
12
|
this.clear();
|
11
13
|
}
|
@@ -26,7 +28,6 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
26
28
|
return Vec2.of(this.elem.clientWidth, this.elem.clientHeight);
|
27
29
|
}
|
28
30
|
clear() {
|
29
|
-
this.mainGroup = document.createElementNS(svgNameSpace, 'g');
|
30
31
|
// Restore all alltributes
|
31
32
|
for (const attrName in this.overwrittenAttrs) {
|
32
33
|
const value = this.overwrittenAttrs[attrName];
|
@@ -38,13 +39,11 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
38
39
|
}
|
39
40
|
}
|
40
41
|
this.overwrittenAttrs = {};
|
41
|
-
// Remove all children
|
42
|
-
this.elem.replaceChildren(this.mainGroup);
|
43
42
|
}
|
44
43
|
beginPath(startPoint) {
|
45
44
|
var _a;
|
46
45
|
this.currentPath = [];
|
47
|
-
this.pathStart = this.
|
46
|
+
this.pathStart = this.canvasToScreen(startPoint);
|
48
47
|
(_a = this.lastPathStart) !== null && _a !== void 0 ? _a : (this.lastPathStart = this.pathStart);
|
49
48
|
}
|
50
49
|
endPath(style) {
|
@@ -72,6 +71,7 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
72
71
|
}
|
73
72
|
// Push [this.fullPath] to the SVG
|
74
73
|
addPathToSVG() {
|
74
|
+
var _a;
|
75
75
|
if (!this.lastPathStyle || !this.lastPath) {
|
76
76
|
return;
|
77
77
|
}
|
@@ -83,7 +83,8 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
83
83
|
pathElem.setAttribute('stroke', style.stroke.color.toHexString());
|
84
84
|
pathElem.setAttribute('stroke-width', style.stroke.width.toString());
|
85
85
|
}
|
86
|
-
this.
|
86
|
+
this.elem.appendChild(pathElem);
|
87
|
+
(_a = this.objectElems) === null || _a === void 0 ? void 0 : _a.push(pathElem);
|
87
88
|
}
|
88
89
|
startObject(boundingBox) {
|
89
90
|
super.startObject(boundingBox);
|
@@ -91,30 +92,43 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
91
92
|
this.lastPath = null;
|
92
93
|
this.lastPathStart = null;
|
93
94
|
this.lastPathStyle = null;
|
95
|
+
this.objectElems = [];
|
94
96
|
}
|
95
|
-
endObject() {
|
96
|
-
|
97
|
+
endObject(loaderData) {
|
98
|
+
var _a;
|
99
|
+
super.endObject(loaderData);
|
97
100
|
// Don't extend paths across objects
|
98
101
|
this.addPathToSVG();
|
102
|
+
if (loaderData) {
|
103
|
+
// Restore any attributes unsupported by the app.
|
104
|
+
for (const elem of (_a = this.objectElems) !== null && _a !== void 0 ? _a : []) {
|
105
|
+
const attrs = loaderData[svgAttributesDataKey];
|
106
|
+
if (attrs) {
|
107
|
+
for (const [attr, value] of attrs) {
|
108
|
+
elem.setAttribute(attr, value);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
99
113
|
}
|
100
114
|
lineTo(point) {
|
101
|
-
point = this.
|
115
|
+
point = this.canvasToScreen(point);
|
102
116
|
this.currentPath.push({
|
103
117
|
kind: PathCommandType.LineTo,
|
104
118
|
point,
|
105
119
|
});
|
106
120
|
}
|
107
121
|
moveTo(point) {
|
108
|
-
point = this.
|
122
|
+
point = this.canvasToScreen(point);
|
109
123
|
this.currentPath.push({
|
110
124
|
kind: PathCommandType.MoveTo,
|
111
125
|
point,
|
112
126
|
});
|
113
127
|
}
|
114
128
|
traceCubicBezierCurve(controlPoint1, controlPoint2, endPoint) {
|
115
|
-
controlPoint1 = this.
|
116
|
-
controlPoint2 = this.
|
117
|
-
endPoint = this.
|
129
|
+
controlPoint1 = this.canvasToScreen(controlPoint1);
|
130
|
+
controlPoint2 = this.canvasToScreen(controlPoint2);
|
131
|
+
endPoint = this.canvasToScreen(endPoint);
|
118
132
|
this.currentPath.push({
|
119
133
|
kind: PathCommandType.CubicBezierTo,
|
120
134
|
controlPoint1,
|
@@ -123,8 +137,8 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
123
137
|
});
|
124
138
|
}
|
125
139
|
traceQuadraticBezierCurve(controlPoint, endPoint) {
|
126
|
-
controlPoint = this.
|
127
|
-
endPoint = this.
|
140
|
+
controlPoint = this.canvasToScreen(controlPoint);
|
141
|
+
endPoint = this.canvasToScreen(endPoint);
|
128
142
|
this.currentPath.push({
|
129
143
|
kind: PathCommandType.QuadraticBezierTo,
|
130
144
|
controlPoint,
|
@@ -137,11 +151,14 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
137
151
|
elem.setAttribute('cx', `${point.x}`);
|
138
152
|
elem.setAttribute('cy', `${point.y}`);
|
139
153
|
elem.setAttribute('r', '15');
|
140
|
-
this.
|
154
|
+
this.elem.appendChild(elem);
|
141
155
|
});
|
142
156
|
}
|
143
|
-
// Renders a copy of the given element.
|
157
|
+
// Renders a **copy** of the given element.
|
144
158
|
drawSVGElem(elem) {
|
145
159
|
this.elem.appendChild(elem.cloneNode(true));
|
146
160
|
}
|
161
|
+
isTooSmallToRender(_rect) {
|
162
|
+
return false;
|
163
|
+
}
|
147
164
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import Editor from '../Editor';
|
2
2
|
import { ToolbarLocalization } from './localization';
|
3
|
+
import { ActionButtonIcon } from './types';
|
3
4
|
export default class HTMLToolbar {
|
4
5
|
private editor;
|
5
6
|
private localizationTable;
|
@@ -7,7 +8,7 @@ export default class HTMLToolbar {
|
|
7
8
|
private penTypes;
|
8
9
|
constructor(editor: Editor, parent: HTMLElement, localizationTable?: ToolbarLocalization);
|
9
10
|
setupColorPickers(): void;
|
10
|
-
addActionButton(
|
11
|
+
addActionButton(title: string | ActionButtonIcon, command: () => void, parent?: Element): HTMLButtonElement;
|
11
12
|
private addUndoRedoButtons;
|
12
13
|
addDefaultToolWidgets(): void;
|
13
14
|
addDefaultActionButtons(): void;
|