js-draw 1.21.3 → 1.22.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +103 -75
- package/build-config.json +2 -2
- package/dist/Editor.css +29 -16
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.js +36 -22
- package/dist/cjs/EventDispatcher.js +1 -1
- package/dist/cjs/Pointer.js +3 -3
- package/dist/cjs/SVGLoader/SVGLoader.js +13 -6
- package/dist/cjs/UndoRedoHistory.js +1 -1
- package/dist/cjs/Viewport.js +4 -2
- package/dist/cjs/commands/Command.js +7 -5
- package/dist/cjs/commands/Duplicate.js +2 -2
- package/dist/cjs/commands/Erase.js +3 -4
- package/dist/cjs/commands/invertCommand.js +4 -4
- package/dist/cjs/commands/lib.d.ts +1 -1
- package/dist/cjs/commands/uniteCommands.js +4 -4
- package/dist/cjs/components/AbstractComponent.d.ts +1 -1
- package/dist/cjs/components/AbstractComponent.js +3 -3
- package/dist/cjs/components/BackgroundComponent.js +8 -6
- package/dist/cjs/components/ImageComponent.js +12 -5
- package/dist/cjs/components/RestylableComponent.js +1 -1
- package/dist/cjs/components/SVGGlobalAttributesObject.js +1 -2
- package/dist/cjs/components/Stroke.js +37 -24
- package/dist/cjs/components/TextComponent.js +13 -10
- package/dist/cjs/components/UnknownSVGObject.js +2 -3
- package/dist/cjs/components/builders/ArrowBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/ArrowBuilder.js +9 -3
- package/dist/cjs/components/builders/CircleBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/CircleBuilder.js +11 -4
- package/dist/cjs/components/builders/FreehandLineBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/FreehandLineBuilder.js +10 -4
- package/dist/cjs/components/builders/LineBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/LineBuilder.js +8 -4
- package/dist/cjs/components/builders/PolylineBuilder.d.ts +4 -1
- package/dist/cjs/components/builders/PolylineBuilder.js +9 -5
- package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.js +16 -10
- package/dist/cjs/components/builders/RectangleBuilder.d.ts +12 -0
- package/dist/cjs/components/builders/RectangleBuilder.js +17 -3
- package/dist/cjs/components/builders/autocorrect/makeShapeFitAutocorrect.js +5 -8
- package/dist/cjs/components/builders/autocorrect/makeSnapToGridAutocorrect.js +1 -1
- package/dist/cjs/components/builders/lib.d.ts +7 -0
- package/dist/cjs/components/builders/lib.js +18 -0
- package/dist/cjs/components/lib.d.ts +1 -4
- package/dist/cjs/components/lib.js +2 -9
- package/dist/cjs/components/util/StrokeSmoother.js +5 -6
- package/dist/cjs/dialogs/makeAboutDialog.js +1 -1
- package/dist/cjs/dialogs/makeMessageDialog.js +2 -2
- package/dist/cjs/image/EditorImage.js +13 -15
- package/dist/cjs/image/export/editorImageToSVG.js +1 -1
- package/dist/cjs/inputEvents.js +3 -3
- package/dist/cjs/lib.d.ts +2 -2
- package/dist/cjs/localizations/de.js +2 -2
- package/dist/cjs/localizations/es.js +7 -3
- package/dist/cjs/rendering/Display.js +7 -3
- package/dist/cjs/rendering/RenderablePathSpec.js +26 -11
- package/dist/cjs/rendering/RenderingStyle.js +22 -15
- package/dist/cjs/rendering/TextRenderingStyle.js +1 -1
- package/dist/cjs/rendering/caching/CacheRecord.js +1 -1
- package/dist/cjs/rendering/caching/CacheRecordManager.js +1 -1
- package/dist/cjs/rendering/caching/RenderingCache.js +1 -1
- package/dist/cjs/rendering/caching/RenderingCacheNode.js +26 -15
- package/dist/cjs/rendering/caching/testUtils.js +2 -2
- package/dist/cjs/rendering/renderers/AbstractRenderer.js +3 -1
- package/dist/cjs/rendering/renderers/CanvasRenderer.js +4 -3
- package/dist/cjs/rendering/renderers/DummyRenderer.js +1 -1
- package/dist/cjs/rendering/renderers/SVGRenderer.js +37 -19
- package/dist/cjs/rendering/renderers/TextOnlyRenderer.js +13 -15
- package/dist/cjs/shortcuts/KeyBinding.js +6 -12
- package/dist/cjs/shortcuts/KeyboardShortcutManager.js +2 -2
- package/dist/cjs/testing/createEditor.js +6 -1
- package/dist/cjs/testing/findNodeWithText.d.ts +4 -1
- package/dist/cjs/testing/findNodeWithText.js +12 -3
- package/dist/cjs/testing/getUniquePointerId.js +1 -1
- package/dist/cjs/testing/sendHtmlSwipe.js +7 -3
- package/dist/cjs/testing/sendPenEvent.js +1 -3
- package/dist/cjs/testing/sendTouchEvent.js +1 -4
- package/dist/cjs/testing/startPinchGesture.js +3 -1
- package/dist/cjs/toolbar/AbstractToolbar.js +7 -11
- package/dist/cjs/toolbar/EdgeToolbar.js +11 -15
- package/dist/cjs/toolbar/IconProvider.js +5 -3
- package/dist/cjs/toolbar/localization.js +3 -3
- package/dist/cjs/toolbar/utils/HelpDisplay.js +8 -6
- package/dist/cjs/toolbar/utils/makeDraggable.js +4 -7
- package/dist/cjs/toolbar/widgets/BaseToolWidget.js +3 -2
- package/dist/cjs/toolbar/widgets/BaseWidget.js +7 -7
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +2 -2
- package/dist/cjs/toolbar/widgets/EraserToolWidget.js +5 -3
- package/dist/cjs/toolbar/widgets/HandToolWidget.js +8 -6
- package/dist/cjs/toolbar/widgets/InsertImageWidget/InsertImageWidget.js +9 -10
- package/dist/cjs/toolbar/widgets/PenToolWidget.js +22 -13
- package/dist/cjs/toolbar/widgets/SelectionToolWidget.js +2 -2
- package/dist/cjs/toolbar/widgets/TextToolWidget.js +5 -5
- package/dist/cjs/toolbar/widgets/components/makeFileInput.js +7 -7
- package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +5 -5
- package/dist/cjs/toolbar/widgets/components/makeSnappedList.js +9 -5
- package/dist/cjs/toolbar/widgets/keybindings.js +2 -2
- package/dist/cjs/toolbar/widgets/layout/DropdownLayoutManager.js +6 -6
- package/dist/cjs/tools/BaseTool.js +5 -3
- package/dist/cjs/tools/Eraser.js +25 -20
- package/dist/cjs/tools/FindTool.js +2 -2
- package/dist/cjs/tools/InputFilter/ContextMenuRecognizer.js +1 -3
- package/dist/cjs/tools/InputFilter/InputMapper.js +1 -1
- package/dist/cjs/tools/InputFilter/InputPipeline.js +1 -1
- package/dist/cjs/tools/InputFilter/InputStabilizer.js +12 -5
- package/dist/cjs/tools/InputFilter/StrokeKeyboardControl.js +7 -4
- package/dist/cjs/tools/PanZoom.d.ts +1 -1
- package/dist/cjs/tools/PanZoom.js +17 -12
- package/dist/cjs/tools/PasteHandler.js +8 -2
- package/dist/cjs/tools/Pen.js +17 -9
- package/dist/cjs/tools/ScrollbarTool.js +8 -7
- package/dist/cjs/tools/SelectionTool/Selection.js +16 -12
- package/dist/cjs/tools/SelectionTool/SelectionHandle.js +5 -2
- package/dist/cjs/tools/SelectionTool/SelectionMenuShortcut.js +3 -1
- package/dist/cjs/tools/SelectionTool/SelectionTool.js +25 -16
- package/dist/cjs/tools/SelectionTool/ToPointerAutoscroller.js +1 -1
- package/dist/cjs/tools/SelectionTool/TransformMode.js +6 -7
- package/dist/cjs/tools/SelectionTool/util/makeClipboardErrorHandlers.js +23 -2
- package/dist/cjs/tools/SelectionTool/util/showSelectionContextMenu.js +29 -20
- package/dist/cjs/tools/SoundUITool.js +5 -3
- package/dist/cjs/tools/TextTool.js +8 -6
- package/dist/cjs/tools/ToolController.js +16 -10
- package/dist/cjs/tools/localization.d.ts +2 -0
- package/dist/cjs/tools/localization.js +3 -1
- package/dist/cjs/tools/util/StationaryPenDetector.js +3 -3
- package/dist/cjs/tools/util/createMenuOverlay.js +2 -2
- package/dist/cjs/util/ClipboardHandler.d.ts +1 -1
- package/dist/cjs/util/ClipboardHandler.js +19 -18
- package/dist/cjs/util/ReactiveValue.js +16 -12
- package/dist/cjs/util/adjustEditorThemeForContrast.js +6 -2
- package/dist/cjs/util/guessKeyCodeFromKey.js +1 -1
- package/dist/cjs/util/listenForKeyboardEventsFrom.js +8 -6
- package/dist/cjs/util/waitForAll.js +3 -3
- package/dist/cjs/util/waitForImageLoaded.js +3 -3
- package/dist/cjs/util/waitForTimeout.js +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.mjs +37 -23
- package/dist/mjs/EventDispatcher.mjs +1 -1
- package/dist/mjs/Pointer.mjs +3 -3
- package/dist/mjs/SVGLoader/SVGLoader.mjs +14 -7
- package/dist/mjs/UndoRedoHistory.mjs +1 -1
- package/dist/mjs/Viewport.mjs +4 -2
- package/dist/mjs/commands/Command.mjs +7 -5
- package/dist/mjs/commands/Duplicate.mjs +2 -2
- package/dist/mjs/commands/Erase.mjs +3 -4
- package/dist/mjs/commands/invertCommand.mjs +4 -4
- package/dist/mjs/commands/lib.d.ts +1 -1
- package/dist/mjs/commands/lib.mjs +1 -1
- package/dist/mjs/commands/uniteCommands.mjs +4 -4
- package/dist/mjs/components/AbstractComponent.d.ts +1 -1
- package/dist/mjs/components/AbstractComponent.mjs +3 -3
- package/dist/mjs/components/BackgroundComponent.mjs +10 -8
- package/dist/mjs/components/ImageComponent.mjs +12 -5
- package/dist/mjs/components/RestylableComponent.mjs +2 -2
- package/dist/mjs/components/SVGGlobalAttributesObject.mjs +1 -2
- package/dist/mjs/components/Stroke.mjs +40 -27
- package/dist/mjs/components/TextComponent.mjs +15 -12
- package/dist/mjs/components/UnknownSVGObject.mjs +2 -3
- package/dist/mjs/components/builders/ArrowBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/ArrowBuilder.mjs +9 -3
- package/dist/mjs/components/builders/CircleBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/CircleBuilder.mjs +11 -4
- package/dist/mjs/components/builders/FreehandLineBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/FreehandLineBuilder.mjs +10 -4
- package/dist/mjs/components/builders/LineBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/LineBuilder.mjs +8 -4
- package/dist/mjs/components/builders/PolylineBuilder.d.ts +4 -1
- package/dist/mjs/components/builders/PolylineBuilder.mjs +10 -6
- package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.mjs +17 -11
- package/dist/mjs/components/builders/RectangleBuilder.d.ts +12 -0
- package/dist/mjs/components/builders/RectangleBuilder.mjs +17 -3
- package/dist/mjs/components/builders/autocorrect/makeShapeFitAutocorrect.mjs +5 -8
- package/dist/mjs/components/builders/autocorrect/makeSnapToGridAutocorrect.mjs +1 -1
- package/dist/mjs/components/builders/lib.d.ts +7 -0
- package/dist/mjs/components/builders/lib.mjs +7 -0
- package/dist/mjs/components/lib.d.ts +1 -4
- package/dist/mjs/components/lib.mjs +2 -5
- package/dist/mjs/components/util/StrokeSmoother.mjs +5 -6
- package/dist/mjs/dialogs/makeAboutDialog.mjs +1 -1
- package/dist/mjs/dialogs/makeMessageDialog.mjs +2 -2
- package/dist/mjs/image/EditorImage.mjs +13 -15
- package/dist/mjs/image/export/editorImageToSVG.mjs +1 -1
- package/dist/mjs/inputEvents.mjs +3 -3
- package/dist/mjs/lib.d.ts +2 -2
- package/dist/mjs/lib.mjs +2 -2
- package/dist/mjs/localization.mjs +2 -2
- package/dist/mjs/localizations/de.mjs +2 -2
- package/dist/mjs/localizations/es.mjs +7 -3
- package/dist/mjs/rendering/Display.mjs +7 -3
- package/dist/mjs/rendering/RenderablePathSpec.mjs +26 -11
- package/dist/mjs/rendering/RenderingStyle.mjs +22 -15
- package/dist/mjs/rendering/TextRenderingStyle.mjs +1 -1
- package/dist/mjs/rendering/caching/CacheRecord.mjs +1 -1
- package/dist/mjs/rendering/caching/CacheRecordManager.mjs +1 -1
- package/dist/mjs/rendering/caching/RenderingCache.mjs +1 -1
- package/dist/mjs/rendering/caching/RenderingCacheNode.mjs +26 -15
- package/dist/mjs/rendering/caching/testUtils.mjs +2 -2
- package/dist/mjs/rendering/renderers/AbstractRenderer.mjs +3 -1
- package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +4 -3
- package/dist/mjs/rendering/renderers/DummyRenderer.mjs +1 -1
- package/dist/mjs/rendering/renderers/SVGRenderer.mjs +38 -20
- package/dist/mjs/rendering/renderers/TextOnlyRenderer.mjs +13 -15
- package/dist/mjs/shortcuts/KeyBinding.mjs +6 -12
- package/dist/mjs/shortcuts/KeyboardShortcutManager.mjs +2 -2
- package/dist/mjs/testing/createEditor.mjs +6 -1
- package/dist/mjs/testing/findNodeWithText.d.ts +4 -1
- package/dist/mjs/testing/findNodeWithText.mjs +12 -3
- package/dist/mjs/testing/getUniquePointerId.mjs +1 -1
- package/dist/mjs/testing/sendHtmlSwipe.mjs +7 -3
- package/dist/mjs/testing/sendPenEvent.mjs +1 -3
- package/dist/mjs/testing/sendTouchEvent.mjs +1 -4
- package/dist/mjs/testing/startPinchGesture.mjs +3 -1
- package/dist/mjs/toolbar/AbstractToolbar.mjs +7 -11
- package/dist/mjs/toolbar/EdgeToolbar.mjs +11 -15
- package/dist/mjs/toolbar/IconProvider.mjs +5 -3
- package/dist/mjs/toolbar/localization.mjs +3 -3
- package/dist/mjs/toolbar/utils/HelpDisplay.mjs +8 -6
- package/dist/mjs/toolbar/utils/makeDraggable.mjs +4 -7
- package/dist/mjs/toolbar/widgets/BaseToolWidget.mjs +3 -2
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +8 -8
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +2 -2
- package/dist/mjs/toolbar/widgets/EraserToolWidget.mjs +5 -3
- package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +8 -6
- package/dist/mjs/toolbar/widgets/InsertImageWidget/InsertImageWidget.mjs +9 -10
- package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +23 -14
- package/dist/mjs/toolbar/widgets/SelectionToolWidget.mjs +2 -2
- package/dist/mjs/toolbar/widgets/TextToolWidget.mjs +5 -5
- package/dist/mjs/toolbar/widgets/components/makeFileInput.mjs +7 -7
- package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +5 -5
- package/dist/mjs/toolbar/widgets/components/makeSnappedList.mjs +9 -5
- package/dist/mjs/toolbar/widgets/keybindings.mjs +2 -2
- package/dist/mjs/toolbar/widgets/layout/DropdownLayoutManager.mjs +6 -6
- package/dist/mjs/tools/BaseTool.mjs +6 -4
- package/dist/mjs/tools/Eraser.mjs +25 -20
- package/dist/mjs/tools/FindTool.mjs +2 -2
- package/dist/mjs/tools/InputFilter/ContextMenuRecognizer.mjs +2 -4
- package/dist/mjs/tools/InputFilter/InputMapper.mjs +1 -1
- package/dist/mjs/tools/InputFilter/InputPipeline.mjs +1 -1
- package/dist/mjs/tools/InputFilter/InputStabilizer.mjs +13 -6
- package/dist/mjs/tools/InputFilter/StrokeKeyboardControl.mjs +7 -4
- package/dist/mjs/tools/PanZoom.d.ts +1 -1
- package/dist/mjs/tools/PanZoom.mjs +18 -13
- package/dist/mjs/tools/PasteHandler.mjs +8 -2
- package/dist/mjs/tools/Pen.mjs +18 -10
- package/dist/mjs/tools/ScrollbarTool.mjs +8 -7
- package/dist/mjs/tools/SelectionTool/Selection.mjs +16 -12
- package/dist/mjs/tools/SelectionTool/SelectionHandle.mjs +5 -2
- package/dist/mjs/tools/SelectionTool/SelectionMenuShortcut.mjs +3 -1
- package/dist/mjs/tools/SelectionTool/SelectionTool.mjs +26 -17
- package/dist/mjs/tools/SelectionTool/ToPointerAutoscroller.mjs +1 -1
- package/dist/mjs/tools/SelectionTool/TransformMode.mjs +6 -7
- package/dist/mjs/tools/SelectionTool/util/makeClipboardErrorHandlers.mjs +23 -2
- package/dist/mjs/tools/SelectionTool/util/showSelectionContextMenu.mjs +29 -20
- package/dist/mjs/tools/SoundUITool.mjs +5 -3
- package/dist/mjs/tools/TextTool.mjs +8 -6
- package/dist/mjs/tools/ToolController.mjs +16 -10
- package/dist/mjs/tools/localization.d.ts +2 -0
- package/dist/mjs/tools/localization.mjs +3 -1
- package/dist/mjs/tools/util/StationaryPenDetector.mjs +3 -3
- package/dist/mjs/tools/util/createMenuOverlay.mjs +2 -2
- package/dist/mjs/util/ClipboardHandler.d.ts +1 -1
- package/dist/mjs/util/ClipboardHandler.mjs +19 -18
- package/dist/mjs/util/ReactiveValue.mjs +16 -12
- package/dist/mjs/util/adjustEditorThemeForContrast.mjs +6 -2
- package/dist/mjs/util/guessKeyCodeFromKey.mjs +1 -1
- package/dist/mjs/util/listenForKeyboardEventsFrom.mjs +8 -6
- package/dist/mjs/util/waitForAll.mjs +3 -3
- package/dist/mjs/util/waitForImageLoaded.mjs +3 -3
- package/dist/mjs/util/waitForTimeout.mjs +1 -1
- package/dist/mjs/version.mjs +1 -1
- package/package.json +88 -88
- package/src/Coloris.css +6 -6
- package/src/Editor.scss +7 -5
- package/src/dialogs/dialogs.scss +3 -4
- package/src/dialogs/makeAboutDialog.scss +2 -2
- package/src/dialogs/makeMessageDialog.scss +11 -7
- package/src/styles.js +1 -1
- package/src/toolbar/AbstractToolbar.scss +20 -12
- package/src/toolbar/DropdownToolbar.scss +5 -4
- package/src/toolbar/EdgeToolbar.scss +65 -31
- package/src/toolbar/toolbar.scss +5 -5
- package/src/toolbar/utils/HelpDisplay.scss +48 -25
- package/src/toolbar/utils/labelVisibleOnHover.scss +39 -16
- package/src/toolbar/widgets/DocumentPropertiesWidget.scss +0 -1
- package/src/toolbar/widgets/HandToolWidget.scss +0 -1
- package/src/toolbar/widgets/InsertImageWidget/InsertImageWidget.scss +2 -3
- package/src/toolbar/widgets/OverflowWidget.css +1 -2
- package/src/toolbar/widgets/PenToolWidget.scss +0 -2
- package/src/toolbar/widgets/SelectionToolWidget.scss +1 -2
- package/src/toolbar/widgets/components/components.scss +6 -6
- package/src/toolbar/widgets/components/makeColorInput.scss +0 -2
- package/src/toolbar/widgets/components/makeFileInput.scss +5 -7
- package/src/toolbar/widgets/components/makeGridSelector.scss +6 -9
- package/src/toolbar/widgets/components/makeSnappedList.scss +3 -4
- package/src/toolbar/widgets/components/makeThicknessSlider.scss +1 -2
- package/src/toolbar/widgets/widgets.scss +7 -7
- package/src/tools/FindTool.css +1 -2
- package/src/tools/ScrollbarTool.scss +9 -5
- package/src/tools/SelectionTool/SelectionTool.scss +15 -7
- package/src/tools/SelectionTool/util/makeClipboardErrorHandlers.scss +1 -2
- package/src/tools/SoundUITool.scss +4 -4
- package/src/tools/tools.scss +5 -6
- package/src/tools/util/createMenuOverlay.scss +10 -4
- package/tsconfig.json +1 -3
- package/typedoc.json +1 -1
@@ -2,9 +2,21 @@ import { Mat33, Rect2, Path } from '@js-draw/math';
|
|
2
2
|
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
3
3
|
import Stroke from '../Stroke.mjs';
|
4
4
|
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
5
|
+
/**
|
6
|
+
* Creates filled rectangles with sharp corners.
|
7
|
+
*
|
8
|
+
* Example:
|
9
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
10
|
+
*/
|
5
11
|
export const makeFilledRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
6
12
|
return new RectangleBuilder(initialPoint, true, viewport);
|
7
13
|
});
|
14
|
+
/**
|
15
|
+
* Creates outlined rectangles with sharp corners.
|
16
|
+
*
|
17
|
+
* Example:
|
18
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
19
|
+
*/
|
8
20
|
export const makeOutlinedRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
9
21
|
return new RectangleBuilder(initialPoint, false, viewport);
|
10
22
|
});
|
@@ -28,12 +40,14 @@ export default class RectangleBuilder {
|
|
28
40
|
const startPoint = rotationMat.inverse().transformVec2(this.startPoint.pos);
|
29
41
|
const endPoint = rotationMat.inverse().transformVec2(this.endPoint.pos);
|
30
42
|
const rect = Rect2.fromCorners(startPoint, endPoint);
|
31
|
-
const path = Path.fromRect(rect, this.filled ? null : this.endPoint.width)
|
43
|
+
const path = Path.fromRect(rect, this.filled ? null : this.endPoint.width)
|
44
|
+
.transformedBy(
|
32
45
|
// Rotate the canvas rectangle so that its rotation matches the screen
|
33
|
-
rotationMat)
|
46
|
+
rotationMat)
|
47
|
+
.mapPoints((point) => this.viewport.roundPoint(point));
|
34
48
|
const preview = new Stroke([
|
35
49
|
pathToRenderable(path, {
|
36
|
-
fill: this.endPoint.color
|
50
|
+
fill: this.endPoint.color,
|
37
51
|
}),
|
38
52
|
]);
|
39
53
|
return preview;
|
@@ -6,14 +6,11 @@ const makeShapeFitAutocorrect = (sourceFactory) => {
|
|
6
6
|
};
|
7
7
|
export default makeShapeFitAutocorrect;
|
8
8
|
const makeLineTemplate = (startPoint, points, _bbox) => {
|
9
|
-
const templatePoints = [
|
10
|
-
|
11
|
-
points[points.length - 1],
|
12
|
-
];
|
13
|
-
return { points: templatePoints, };
|
9
|
+
const templatePoints = [startPoint, points[points.length - 1]];
|
10
|
+
return { points: templatePoints };
|
14
11
|
};
|
15
12
|
const makeRectangleTemplate = (_startPoint, _points, bbox) => {
|
16
|
-
return { points: [...bbox.corners, bbox.corners[0]]
|
13
|
+
return { points: [...bbox.corners, bbox.corners[0]] };
|
17
14
|
};
|
18
15
|
class ShapeFitBuilder {
|
19
16
|
constructor(sourceFactory, startPoint, viewport) {
|
@@ -39,10 +36,10 @@ class ShapeFitBuilder {
|
|
39
36
|
async autocorrectShape() {
|
40
37
|
// Use screen points so that autocorrected shapes rotate with the screen.
|
41
38
|
const startPoint = this.viewport.canvasToScreen(this.startPoint.pos);
|
42
|
-
const points = this.points.map(point => this.viewport.canvasToScreen(point.pos));
|
39
|
+
const points = this.points.map((point) => this.viewport.canvasToScreen(point.pos));
|
43
40
|
const bbox = Rect2.bboxOf(points);
|
44
41
|
const snappedStartPoint = this.viewport.canvasToScreen(this.viewport.snapToGrid(this.startPoint.pos));
|
45
|
-
const snappedPoints = this.points.map(point => this.viewport.canvasToScreen(this.viewport.snapToGrid(point.pos)));
|
42
|
+
const snappedPoints = this.points.map((point) => this.viewport.canvasToScreen(this.viewport.snapToGrid(point.pos)));
|
46
43
|
const snappedBBox = Rect2.bboxOf(snappedPoints);
|
47
44
|
// Only fit larger shapes
|
48
45
|
if (bbox.maxDimension < 32) {
|
@@ -35,7 +35,7 @@ class SnapToGridAutocompleteBuilder {
|
|
35
35
|
// Use screen points so that snapped shapes rotate with the screen.
|
36
36
|
const startPoint = snapToGrid(this.startPoint);
|
37
37
|
const builder = this.sourceFactory(startPoint, this.viewport);
|
38
|
-
const points = this.points.map(point => snapToGrid(point));
|
38
|
+
const points = this.points.map((point) => snapToGrid(point));
|
39
39
|
for (const point of points) {
|
40
40
|
builder.addPoint(point);
|
41
41
|
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
export { makeFreehandLineBuilder } from './FreehandLineBuilder';
|
2
|
+
export { makePolylineBuilder } from './PolylineBuilder';
|
3
|
+
export { makePressureSensitiveFreehandLineBuilder } from './PressureSensitiveFreehandLineBuilder';
|
4
|
+
export { makeOutlinedCircleBuilder } from './CircleBuilder';
|
5
|
+
export { makeArrowBuilder } from './ArrowBuilder';
|
6
|
+
export { makeLineBuilder } from './LineBuilder';
|
7
|
+
export { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from './RectangleBuilder';
|
@@ -0,0 +1,7 @@
|
|
1
|
+
export { makeFreehandLineBuilder } from './FreehandLineBuilder.mjs';
|
2
|
+
export { makePolylineBuilder } from './PolylineBuilder.mjs';
|
3
|
+
export { makePressureSensitiveFreehandLineBuilder } from './PressureSensitiveFreehandLineBuilder.mjs';
|
4
|
+
export { makeOutlinedCircleBuilder } from './CircleBuilder.mjs';
|
5
|
+
export { makeArrowBuilder } from './ArrowBuilder.mjs';
|
6
|
+
export { makeLineBuilder } from './LineBuilder.mjs';
|
7
|
+
export { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from './RectangleBuilder.mjs';
|
@@ -1,8 +1,5 @@
|
|
1
1
|
export * from './builders/types';
|
2
|
-
export
|
3
|
-
export { makePolylineBuilder } from './builders/PolylineBuilder';
|
4
|
-
export { makePressureSensitiveFreehandLineBuilder } from './builders/PressureSensitiveFreehandLineBuilder';
|
5
|
-
export { makeOutlinedCircleBuilder } from './builders/CircleBuilder';
|
2
|
+
export * from './builders/lib';
|
6
3
|
export { default as StrokeSmoother, Curve as StrokeSmootherCurve } from './util/StrokeSmoother';
|
7
4
|
export * from './AbstractComponent';
|
8
5
|
export { default as AbstractComponent } from './AbstractComponent';
|
@@ -1,15 +1,12 @@
|
|
1
1
|
export * from './builders/types.mjs';
|
2
|
-
export
|
3
|
-
export { makePolylineBuilder } from './builders/PolylineBuilder.mjs';
|
4
|
-
export { makePressureSensitiveFreehandLineBuilder } from './builders/PressureSensitiveFreehandLineBuilder.mjs';
|
5
|
-
export { makeOutlinedCircleBuilder } from './builders/CircleBuilder.mjs';
|
2
|
+
export * from './builders/lib.mjs';
|
6
3
|
export { default as StrokeSmoother } from './util/StrokeSmoother.mjs';
|
7
4
|
export * from './AbstractComponent.mjs';
|
8
5
|
export { default as AbstractComponent } from './AbstractComponent.mjs';
|
9
6
|
import Stroke from './Stroke.mjs';
|
10
7
|
import TextComponent from './TextComponent.mjs';
|
11
8
|
import ImageComponent from './ImageComponent.mjs';
|
12
|
-
import { createRestyleComponentCommand, isRestylableComponent } from './RestylableComponent.mjs';
|
9
|
+
import { createRestyleComponentCommand, isRestylableComponent, } from './RestylableComponent.mjs';
|
13
10
|
import BackgroundComponent, { BackgroundType } from './BackgroundComponent.mjs';
|
14
11
|
export { Stroke, createRestyleComponentCommand, isRestylableComponent, TextComponent,
|
15
12
|
/** @deprecated use {@link TextComponent} */
|
@@ -53,9 +53,7 @@ export class StrokeSmoother {
|
|
53
53
|
console.assert(this.lastExitingVec.magnitude() !== 0, 'lastExitingVec has zero length!');
|
54
54
|
// Use the last two points to start a new curve (the last point isn't used
|
55
55
|
// in the current curve and we want connected curves to share end points)
|
56
|
-
this.buffer = [
|
57
|
-
this.buffer[this.buffer.length - 2], lastPoint,
|
58
|
-
];
|
56
|
+
this.buffer = [this.buffer[this.buffer.length - 2], lastPoint];
|
59
57
|
this.currentCurve = null;
|
60
58
|
this.isFirstSegment = false;
|
61
59
|
}
|
@@ -96,8 +94,7 @@ export class StrokeSmoother {
|
|
96
94
|
return;
|
97
95
|
}
|
98
96
|
const threshold = Math.min(this.lastPoint.width, newPoint.width) / 3;
|
99
|
-
const shouldSnapToInitial = this.startPoint.pos.distanceTo(newPoint.pos) < threshold
|
100
|
-
&& this.isFirstSegment;
|
97
|
+
const shouldSnapToInitial = this.startPoint.pos.distanceTo(newPoint.pos) < threshold && this.isFirstSegment;
|
101
98
|
// Snap to the starting point if the stroke is contained within a small ball centered
|
102
99
|
// at the starting point.
|
103
100
|
// This allows us to create a circle/dot at the start of the stroke.
|
@@ -150,7 +147,9 @@ export class StrokeSmoother {
|
|
150
147
|
const startEndDist = segmentEnd.distanceTo(segmentStart);
|
151
148
|
const maxControlPointDist = maxRelativeLength * startEndDist;
|
152
149
|
// Exit in cases where we would divide by zero
|
153
|
-
if (maxControlPointDist === 0 ||
|
150
|
+
if (maxControlPointDist === 0 ||
|
151
|
+
exitingVec.magnitude() === 0 ||
|
152
|
+
!isFinite(exitingVec.magnitude())) {
|
154
153
|
return;
|
155
154
|
}
|
156
155
|
console.assert(isFinite(enteringVec.magnitude()), 'Pre-normalized enteringVec has NaN or ∞ magnitude!');
|
@@ -8,7 +8,7 @@ const makeAboutDialog = (editor, entries) => {
|
|
8
8
|
const container = document.createElement(entry.minimized ? 'details' : 'div');
|
9
9
|
container.classList.add('about-entry');
|
10
10
|
const header = document.createElement(entry.minimized ? 'summary' : 'h2');
|
11
|
-
if (typeof
|
11
|
+
if (typeof entry.heading === 'string') {
|
12
12
|
header.innerText = entry.heading;
|
13
13
|
}
|
14
14
|
else {
|
@@ -15,7 +15,7 @@ const makeAboutDialog = (editor, options) => {
|
|
15
15
|
const scrollRegion = document.createElement('div');
|
16
16
|
scrollRegion.classList.add('scroll');
|
17
17
|
// Allow scrolling in the scrollable container -- don't forward wheel events.
|
18
|
-
scrollRegion.onwheel = evt => evt.stopPropagation();
|
18
|
+
scrollRegion.onwheel = (evt) => evt.stopPropagation();
|
19
19
|
contentWrapper.replaceChildren(heading, scrollRegion, closeButton);
|
20
20
|
dialog.replaceChildren(contentWrapper);
|
21
21
|
overlay.replaceChildren(dialog);
|
@@ -27,7 +27,7 @@ const makeAboutDialog = (editor, options) => {
|
|
27
27
|
dialog.close();
|
28
28
|
};
|
29
29
|
const addCloseListeners = () => {
|
30
|
-
dialog.addEventListener('pointerdown', event => {
|
30
|
+
dialog.addEventListener('pointerdown', (event) => {
|
31
31
|
if (event.target === dialog) {
|
32
32
|
void closeDialog();
|
33
33
|
}
|
@@ -121,7 +121,7 @@ class EditorImage {
|
|
121
121
|
getAllElements() {
|
122
122
|
const leaves = this.root.getLeaves();
|
123
123
|
sortLeavesByZIndex(leaves);
|
124
|
-
return leaves.map(leaf => leaf.getContent());
|
124
|
+
return leaves.map((leaf) => leaf.getContent());
|
125
125
|
}
|
126
126
|
/** Returns the number of elements added to this image. @internal */
|
127
127
|
estimateNumElements() {
|
@@ -134,7 +134,7 @@ class EditorImage {
|
|
134
134
|
leaves = leaves.concat(this.background.getLeavesIntersectingRegion(region));
|
135
135
|
}
|
136
136
|
sortLeavesByZIndex(leaves);
|
137
|
-
return leaves.map(leaf => leaf.getContent());
|
137
|
+
return leaves.map((leaf) => leaf.getContent());
|
138
138
|
}
|
139
139
|
/** Called whenever (just after) an element is completely removed. @internal */
|
140
140
|
onDestroyElement(elem) {
|
@@ -474,8 +474,8 @@ export const computeFirstIndexToRender = (sortedLeaves, visibleRect) => {
|
|
474
474
|
for (let i = sortedLeaves.length - 1; i >= 1; i--) {
|
475
475
|
if (
|
476
476
|
// Check for occlusion
|
477
|
-
sortedLeaves[i].getBBox().containsRect(visibleRect)
|
478
|
-
|
477
|
+
sortedLeaves[i].getBBox().containsRect(visibleRect) &&
|
478
|
+
sortedLeaves[i].getContent()?.occludesEverythingBelowWhenRenderedInRect(visibleRect)) {
|
479
479
|
startIndex = i;
|
480
480
|
break;
|
481
481
|
}
|
@@ -510,7 +510,7 @@ export class ImageNode {
|
|
510
510
|
}
|
511
511
|
// Override this to change how children are considered within a given region.
|
512
512
|
getChildrenIntersectingRegion(region, isTooSmallFilter) {
|
513
|
-
return this.children.filter(child => {
|
513
|
+
return this.children.filter((child) => {
|
514
514
|
const bbox = child.getBBox();
|
515
515
|
return !isTooSmallFilter?.(bbox) && bbox.intersects(region);
|
516
516
|
});
|
@@ -601,7 +601,7 @@ export class ImageNode {
|
|
601
601
|
}
|
602
602
|
return nodeForNewLeaf.addLeaf(leaf);
|
603
603
|
}
|
604
|
-
const containingNodes = this.children.filter(child => child.getBBox().containsRect(leafBBox));
|
604
|
+
const containingNodes = this.children.filter((child) => child.getBBox().containsRect(leafBBox));
|
605
605
|
// Does the leaf already fit within one of the children?
|
606
606
|
if (containingNodes.length > 0 && this.children.length >= this.targetChildCount) {
|
607
607
|
// Sort the containers in ascending order by area
|
@@ -639,7 +639,7 @@ export class ImageNode {
|
|
639
639
|
this.bbox = this.content.getBBox();
|
640
640
|
}
|
641
641
|
else {
|
642
|
-
this.bbox = Rect2.union(...this.children.map(child => child.getBBox()));
|
642
|
+
this.bbox = Rect2.union(...this.children.map((child) => child.getBBox()));
|
643
643
|
}
|
644
644
|
if (bubbleUp && !oldBBox.eq(this.bbox)) {
|
645
645
|
if (this.bbox.containsRect(oldBBox)) {
|
@@ -674,7 +674,7 @@ export class ImageNode {
|
|
674
674
|
const oldParent = this.parent;
|
675
675
|
if (oldParent.parent !== null) {
|
676
676
|
const newParent = oldParent.parent;
|
677
|
-
newParent.children = newParent.children.filter(c => c !== oldParent);
|
677
|
+
newParent.children = newParent.children.filter((c) => c !== oldParent);
|
678
678
|
oldParent.parent = null;
|
679
679
|
oldParent.children = [];
|
680
680
|
this.parent = newParent;
|
@@ -746,11 +746,11 @@ export class ImageNode {
|
|
746
746
|
removeChild(child) {
|
747
747
|
this.checkRep();
|
748
748
|
const oldChildCount = this.children.length;
|
749
|
-
this.children = this.children.filter(node => {
|
749
|
+
this.children = this.children.filter((node) => {
|
750
750
|
return node !== child;
|
751
751
|
});
|
752
752
|
console.assert(this.children.length === oldChildCount - 1, `${oldChildCount - 1} ≠ ${this.children.length} after removing all nodes equal to ${child}. Nodes should only be removed once.`);
|
753
|
-
this.children.forEach(child => {
|
753
|
+
this.children.forEach((child) => {
|
754
754
|
child.rebalance();
|
755
755
|
});
|
756
756
|
this.recomputeBBox(true);
|
@@ -799,7 +799,7 @@ export class ImageNode {
|
|
799
799
|
render(renderer, visibleRect) {
|
800
800
|
let leaves;
|
801
801
|
if (visibleRect) {
|
802
|
-
leaves = this.getLeavesIntersectingRegion(visibleRect, rect => renderer.isTooSmallToRender(rect));
|
802
|
+
leaves = this.getLeavesIntersectingRegion(visibleRect, (rect) => renderer.isTooSmallToRender(rect));
|
803
803
|
}
|
804
804
|
else {
|
805
805
|
leaves = this.getLeaves();
|
@@ -909,10 +909,8 @@ export class RootImageNode extends ImageNode {
|
|
909
909
|
};
|
910
910
|
// Check whether the child is stored in the data/fullscreen
|
911
911
|
// component arrays first.
|
912
|
-
this.dataComponents = this.dataComponents
|
913
|
-
|
914
|
-
this.fullscreenChildren = this.fullscreenChildren
|
915
|
-
.filter(checkTargetChild);
|
912
|
+
this.dataComponents = this.dataComponents.filter(checkTargetChild);
|
913
|
+
this.fullscreenChildren = this.fullscreenChildren.filter(checkTargetChild);
|
916
914
|
if (!removed) {
|
917
915
|
super.removeChild(child);
|
918
916
|
}
|
@@ -45,7 +45,7 @@ export const editorImageToSVGSync = (image, options) => {
|
|
45
45
|
}, options);
|
46
46
|
};
|
47
47
|
export const editorImageToSVGAsync = (image, preRenderComponent, options) => {
|
48
|
-
return new Promise(resolve => {
|
48
|
+
return new Promise((resolve) => {
|
49
49
|
toSVGInternal(image, async (renderer, onComplete) => {
|
50
50
|
await image.renderAllAsync(renderer, preRenderComponent);
|
51
51
|
const result = onComplete();
|
package/dist/mjs/inputEvents.mjs
CHANGED
@@ -29,7 +29,7 @@ export const keyPressEventFromHTMLEvent = (event) => {
|
|
29
29
|
return keyEventFromHTMLEvent(InputEvtType.KeyPressEvent, event);
|
30
30
|
};
|
31
31
|
export const isPointerEvt = (event) => {
|
32
|
-
return event.kind === InputEvtType.PointerDownEvt
|
33
|
-
|
34
|
-
|
32
|
+
return (event.kind === InputEvtType.PointerDownEvt ||
|
33
|
+
event.kind === InputEvtType.PointerMoveEvt ||
|
34
|
+
event.kind === InputEvtType.PointerUpEvt);
|
35
35
|
};
|
package/dist/mjs/lib.d.ts
CHANGED
@@ -18,7 +18,7 @@ import Editor, { EditorSettings } from './Editor';
|
|
18
18
|
export * from './image/lib';
|
19
19
|
export * from './types';
|
20
20
|
export * from './inputEvents';
|
21
|
-
export { default as getLocalizationTable, matchingLocalizationTable } from './localizations/getLocalizationTable';
|
21
|
+
export { default as getLocalizationTable, matchingLocalizationTable, } from './localizations/getLocalizationTable';
|
22
22
|
export * from './localization';
|
23
23
|
export { default as SVGLoader } from './SVGLoader/SVGLoader';
|
24
24
|
export { default as Viewport } from './Viewport';
|
@@ -36,7 +36,7 @@ export { default as UndoRedoHistory } from './UndoRedoHistory';
|
|
36
36
|
export * from './util/lib';
|
37
37
|
export { default as __js_draw__version } from './version';
|
38
38
|
import AbstractToolbar from './toolbar/AbstractToolbar';
|
39
|
-
export { Editor, EditorSettings, AbstractToolbar
|
39
|
+
export { Editor, EditorSettings, AbstractToolbar };
|
40
40
|
/**
|
41
41
|
* Using the HTMLToolbar alias is deprecated. Use
|
42
42
|
* `AbstractToolbar` instead.
|
package/dist/mjs/lib.mjs
CHANGED
@@ -18,7 +18,7 @@ import Editor from './Editor.mjs';
|
|
18
18
|
export * from './image/lib.mjs';
|
19
19
|
export * from './types.mjs';
|
20
20
|
export * from './inputEvents.mjs';
|
21
|
-
export { default as getLocalizationTable, matchingLocalizationTable } from './localizations/getLocalizationTable.mjs';
|
21
|
+
export { default as getLocalizationTable, matchingLocalizationTable, } from './localizations/getLocalizationTable.mjs';
|
22
22
|
export * from './localization.mjs';
|
23
23
|
export { default as SVGLoader } from './SVGLoader/SVGLoader.mjs';
|
24
24
|
export { default as Viewport } from './Viewport.mjs';
|
@@ -37,7 +37,7 @@ export * from './util/lib.mjs';
|
|
37
37
|
// @internal
|
38
38
|
export { default as __js_draw__version } from './version.mjs';
|
39
39
|
import AbstractToolbar from './toolbar/AbstractToolbar.mjs';
|
40
|
-
export { Editor, AbstractToolbar
|
40
|
+
export { Editor, AbstractToolbar };
|
41
41
|
/**
|
42
42
|
* Using the HTMLToolbar alias is deprecated. Use
|
43
43
|
* `AbstractToolbar` instead.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { defaultCommandLocalization } from './commands/localization.mjs';
|
2
|
-
import { defaultComponentLocalization } from './components/localization.mjs';
|
3
|
-
import { defaultTextRendererLocalization } from './rendering/localization.mjs';
|
2
|
+
import { defaultComponentLocalization, } from './components/localization.mjs';
|
3
|
+
import { defaultTextRendererLocalization, } from './rendering/localization.mjs';
|
4
4
|
import { defaultToolbarLocalization } from './toolbar/localization.mjs';
|
5
5
|
import { defaultToolLocalization } from './tools/localization.mjs';
|
6
6
|
export const defaultEditorLocalization = {
|
@@ -89,11 +89,11 @@ const localization = {
|
|
89
89
|
textNodeCount: (count) => `Es gibt ${count} sichtbare Text-Knotenpunkte.`,
|
90
90
|
textNode: (content) => `Text: ${content}`,
|
91
91
|
imageNodeCount: (nodeCount) => `Es gibt ${nodeCount} sichtbare Bild-Knoten.`,
|
92
|
-
imageNode: label => `Bild: ${label}`,
|
92
|
+
imageNode: (label) => `Bild: ${label}`,
|
93
93
|
unlabeledImageNode: 'Bild ohne Label',
|
94
94
|
rerenderAsText: 'Als Text darstellen',
|
95
95
|
accessibilityInputInstructions: 'Drücke ‚t‘, um den Inhalt des Ansichtsfensters als Text zu lesen. Verwende die Pfeiltasten, um die Ansicht zu verschieben, und klicke und ziehe, um Striche zu zeichnen. Drücke ‚w‘ zum Vergrößern und ‚s‘ zum Verkleinern der Ansicht.',
|
96
|
-
loading: percentage => `Laden ${percentage}%...`,
|
96
|
+
loading: (percentage) => `Laden ${percentage}%...`,
|
97
97
|
doneLoading: 'Laden fertig',
|
98
98
|
imageEditor: 'Bild-Editor',
|
99
99
|
undoAnnouncement: (commandDescription) => `${commandDescription} rückgängig gemacht`,
|
@@ -46,9 +46,13 @@ const localization = {
|
|
46
46
|
selectionMenu__duplicate: 'Duplicar',
|
47
47
|
closeSidebar: (toolName) => `Close sidebar for ${toolName}`,
|
48
48
|
dropdownShown: (toolName) => `Menú por ${toolName} es visible`,
|
49
|
-
dropdownHidden: (toolName) => {
|
49
|
+
dropdownHidden: (toolName) => {
|
50
|
+
return `Menú por ${toolName} fue ocultado`;
|
51
|
+
},
|
50
52
|
zoomLevel: (zoomPercent) => `Zoom: ${zoomPercent}%`,
|
51
|
-
colorChangedAnnouncement: (color) => {
|
53
|
+
colorChangedAnnouncement: (color) => {
|
54
|
+
return `Color fue cambiado a ${color}`;
|
55
|
+
},
|
52
56
|
imageSize: (size, units) => `Tamaño del imagen: ${size} ${units}`,
|
53
57
|
imageLoadError: (message) => `Error cargando imagen: ${message}`,
|
54
58
|
penTool: (penId) => `Lapiz ${penId}`,
|
@@ -65,7 +69,7 @@ const localization = {
|
|
65
69
|
closeDialog: 'Cerrar',
|
66
70
|
anyDevicePanning: 'Mover la pantalla con todo dispotivo',
|
67
71
|
copied: (count) => `${count} cosas fueron copiados`,
|
68
|
-
pasted: (count) => count === 1 ? 'Pegado' : `${count} cosas fueron pegados
|
72
|
+
pasted: (count) => (count === 1 ? 'Pegado' : `${count} cosas fueron pegados`),
|
69
73
|
toolEnabledAnnouncement: (toolName) => `${toolName} fue activado`,
|
70
74
|
toolDisabledAnnouncement: (toolName) => `${toolName} fue desactivado`,
|
71
75
|
resizeOutputCommand: (newSize) => `Tamaño de imagen fue cambiado a ${newSize.w}x${newSize.h}`,
|
@@ -79,7 +79,7 @@ export default class Display {
|
|
79
79
|
// Require about 105 strokes with 4 parts each to use the cache at all.
|
80
80
|
minProportionalRenderTimeToUseCache: 105 * 4,
|
81
81
|
});
|
82
|
-
this.editor.notifier.on(EditorEventType.DisplayResized, event => {
|
82
|
+
this.editor.notifier.on(EditorEventType.DisplayResized, (event) => {
|
83
83
|
if (event.kind !== EditorEventType.DisplayResized) {
|
84
84
|
throw new Error('Mismatched event.kinds!');
|
85
85
|
}
|
@@ -117,10 +117,14 @@ export default class Display {
|
|
117
117
|
}
|
118
118
|
this.resizeSurfacesCallback = () => {
|
119
119
|
const expectedWidth = (canvas) => {
|
120
|
-
|
120
|
+
const widthInPixels = Math.ceil(canvas.clientWidth * this.devicePixelRatio);
|
121
|
+
// Avoid setting the canvas width to zero -- doing so can cause errors when attempting
|
122
|
+
// to use the canvas:
|
123
|
+
return widthInPixels || canvas.width;
|
121
124
|
};
|
122
125
|
const expectedHeight = (canvas) => {
|
123
|
-
|
126
|
+
const heightInPixels = Math.ceil(canvas.clientHeight * this.devicePixelRatio);
|
127
|
+
return heightInPixels || canvas.height; // Zero-size canvases can cause errors.
|
124
128
|
};
|
125
129
|
const hasSizeMismatch = (canvas) => {
|
126
130
|
return expectedHeight(canvas) !== canvas.height || expectedWidth(canvas) !== canvas.width;
|
@@ -37,15 +37,18 @@ const pathIncluded = (renderablePath, path) => {
|
|
37
37
|
*
|
38
38
|
* @internal
|
39
39
|
*/
|
40
|
-
export const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, options = {
|
40
|
+
export const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, options = {
|
41
|
+
fastCheck: true,
|
42
|
+
expensiveCheck: true,
|
43
|
+
}) => {
|
41
44
|
const path = pathFromRenderable(renderablePath);
|
42
45
|
const strokeWidth = renderablePath.style.stroke?.width ?? 0;
|
43
46
|
const onlyStroked = strokeWidth > 0 && renderablePath.style.fill.a === 0;
|
44
47
|
const styledPathBBox = path.bbox.grownBy(strokeWidth);
|
45
48
|
// Are we close enough to the path that it fills the entire screen?
|
46
|
-
const isOnlyStrokedAndCouldFillScreen =
|
47
|
-
|
48
|
-
|
49
|
+
const isOnlyStrokedAndCouldFillScreen = onlyStroked &&
|
50
|
+
strokeWidth > visibleRect.maxDimension &&
|
51
|
+
styledPathBBox.containsRect(visibleRect);
|
49
52
|
if (options.fastCheck && isOnlyStrokedAndCouldFillScreen && renderablePath.style.stroke) {
|
50
53
|
const strokeRadius = strokeWidth / 2;
|
51
54
|
// Are we completely within the stroke?
|
@@ -55,7 +58,9 @@ export const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, opt
|
|
55
58
|
if (visibleRect.isWithinRadiusOf(strokeRadius, point)) {
|
56
59
|
return {
|
57
60
|
rectangle: visibleRect,
|
58
|
-
path: pathToRenderable(Path.fromRect(visibleRect), {
|
61
|
+
path: pathToRenderable(Path.fromRect(visibleRect), {
|
62
|
+
fill: renderablePath.style.stroke.color,
|
63
|
+
}),
|
59
64
|
fullScreen: true,
|
60
65
|
};
|
61
66
|
}
|
@@ -63,13 +68,16 @@ export const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, opt
|
|
63
68
|
}
|
64
69
|
// Try filtering again, but with slightly more expensive checks
|
65
70
|
if (options.expensiveCheck &&
|
66
|
-
isOnlyStrokedAndCouldFillScreen &&
|
67
|
-
|
71
|
+
isOnlyStrokedAndCouldFillScreen &&
|
72
|
+
renderablePath.style.stroke &&
|
73
|
+
strokeWidth > visibleRect.maxDimension * 3) {
|
68
74
|
const signedDist = path.signedDistance(visibleRect.center, strokeWidth / 2);
|
69
75
|
const margin = strokeWidth / 6;
|
70
76
|
if (signedDist < -visibleRect.maxDimension / 2 - margin) {
|
71
77
|
return {
|
72
|
-
path: pathToRenderable(Path.fromRect(visibleRect), {
|
78
|
+
path: pathToRenderable(Path.fromRect(visibleRect), {
|
79
|
+
fill: renderablePath.style.stroke.color,
|
80
|
+
}),
|
73
81
|
rectangle: visibleRect,
|
74
82
|
fullScreen: true,
|
75
83
|
};
|
@@ -92,12 +100,16 @@ export const visualEquivalent = (renderablePath, visibleRect) => {
|
|
92
100
|
const strokeWidth = renderablePath.style.stroke?.width ?? 0;
|
93
101
|
const onlyStroked = strokeWidth > 0 && renderablePath.style.fill.a === 0;
|
94
102
|
const styledPathBBox = path.bbox.grownBy(strokeWidth);
|
95
|
-
let rectangleSimplification = simplifyPathToFullScreenOrEmpty(renderablePath, visibleRect, {
|
103
|
+
let rectangleSimplification = simplifyPathToFullScreenOrEmpty(renderablePath, visibleRect, {
|
104
|
+
fastCheck: true,
|
105
|
+
expensiveCheck: false,
|
106
|
+
});
|
96
107
|
if (rectangleSimplification) {
|
97
108
|
return rectangleSimplification.path;
|
98
109
|
}
|
99
110
|
// Scale the expanded rect --- the visual equivalent is only close for huge strokes.
|
100
|
-
const expandedRect = visibleRect
|
111
|
+
const expandedRect = visibleRect
|
112
|
+
.grownBy(strokeWidth)
|
101
113
|
.transformedBoundingBox(Mat33.scaling2D(4, visibleRect.center));
|
102
114
|
// TODO: Handle simplifying very small paths.
|
103
115
|
if (expandedRect.containsRect(styledPathBBox)) {
|
@@ -138,7 +150,10 @@ export const visualEquivalent = (renderablePath, visibleRect) => {
|
|
138
150
|
}
|
139
151
|
const newPath = new Path(path.startPoint, parts);
|
140
152
|
const newStyle = renderablePath.style;
|
141
|
-
rectangleSimplification = simplifyPathToFullScreenOrEmpty(renderablePath, visibleRect, {
|
153
|
+
rectangleSimplification = simplifyPathToFullScreenOrEmpty(renderablePath, visibleRect, {
|
154
|
+
fastCheck: false,
|
155
|
+
expensiveCheck: true,
|
156
|
+
});
|
142
157
|
if (rectangleSimplification) {
|
143
158
|
return rectangleSimplification.path;
|
144
159
|
}
|
@@ -2,36 +2,43 @@ import { Color4 } from '@js-draw/math';
|
|
2
2
|
export const cloneStyle = (style) => {
|
3
3
|
return {
|
4
4
|
fill: style.fill,
|
5
|
-
stroke: style.stroke
|
6
|
-
|
7
|
-
|
5
|
+
stroke: style.stroke
|
6
|
+
? {
|
7
|
+
...style.stroke,
|
8
|
+
}
|
9
|
+
: undefined,
|
8
10
|
};
|
9
11
|
};
|
10
12
|
export const stylesEqual = (a, b) => {
|
11
|
-
const result = a === b ||
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
const result = a === b ||
|
14
|
+
(a.fill.eq(b.fill) &&
|
15
|
+
(a.stroke == undefined) === (b.stroke == undefined) &&
|
16
|
+
(a.stroke?.color?.eq(b.stroke?.color) ?? true) &&
|
17
|
+
a.stroke?.width === b.stroke?.width);
|
15
18
|
// Map undefined/null -> false
|
16
19
|
return result ?? false;
|
17
20
|
};
|
18
21
|
// Returns an object that can be converted to a JSON string with
|
19
22
|
// JSON.stringify.
|
20
23
|
export const styleToJSON = (style) => {
|
21
|
-
const stroke = !style.stroke
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
const stroke = !style.stroke
|
25
|
+
? undefined
|
26
|
+
: {
|
27
|
+
color: style.stroke.color.toHexString(),
|
28
|
+
width: style.stroke.width,
|
29
|
+
};
|
25
30
|
return {
|
26
31
|
fill: style.fill.toHexString(),
|
27
32
|
stroke,
|
28
33
|
};
|
29
34
|
};
|
30
35
|
export const styleFromJSON = (json) => {
|
31
|
-
const stroke = json.stroke
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
const stroke = json.stroke
|
37
|
+
? {
|
38
|
+
color: Color4.fromHex(json.stroke.color),
|
39
|
+
width: json.stroke.width,
|
40
|
+
}
|
41
|
+
: undefined;
|
35
42
|
return {
|
36
43
|
fill: Color4.fromHex(json.fill),
|
37
44
|
stroke,
|
@@ -10,7 +10,7 @@ export const textStyleFromJSON = (json) => {
|
|
10
10
|
if (typeof json === 'string') {
|
11
11
|
json = JSON.parse(json);
|
12
12
|
}
|
13
|
-
if (typeof
|
13
|
+
if (typeof json.fontFamily !== 'string') {
|
14
14
|
throw new Error('Serialized textStyle missing string fontFamily attribute!');
|
15
15
|
}
|
16
16
|
const style = {
|
@@ -15,7 +15,7 @@ export default class CacheRecord {
|
|
15
15
|
startRender() {
|
16
16
|
this.lastUsedCycle = this.cacheState.currentRenderingCycle;
|
17
17
|
if (!this.allocd) {
|
18
|
-
throw new Error(
|
18
|
+
throw new Error("Only alloc'd canvases can be rendered to");
|
19
19
|
}
|
20
20
|
return this.renderer;
|
21
21
|
}
|
@@ -28,7 +28,7 @@ export class CacheRecordManager {
|
|
28
28
|
lru.realloc(onDealloc);
|
29
29
|
lru.setRenderingRegion(drawTo);
|
30
30
|
if (this.cacheState.debugMode) {
|
31
|
-
console.log(
|
31
|
+
console.log("[Cache] Now re-alloc'd. Last used cycle: ", lru.getLastUsedCycle());
|
32
32
|
console.assert(lru['cacheState'] === this.cacheState, '[Cache] Unequal cache states! cacheState should be a shared object!');
|
33
33
|
}
|
34
34
|
return lru;
|
@@ -30,7 +30,7 @@ export default class RenderingCache {
|
|
30
30
|
this.rootNode = this.rootNode.generateParent();
|
31
31
|
}
|
32
32
|
this.rootNode = this.rootNode.smallestChildContaining(visibleRect) ?? this.rootNode;
|
33
|
-
const visibleLeaves = image.getLeavesIntersectingRegion(viewport.visibleRect, rect => screenRenderer.isTooSmallToRender(rect));
|
33
|
+
const visibleLeaves = image.getLeavesIntersectingRegion(viewport.visibleRect, (rect) => screenRenderer.isTooSmallToRender(rect));
|
34
34
|
let approxVisibleRenderTime = 0;
|
35
35
|
for (const leaf of visibleLeaves) {
|
36
36
|
approxVisibleRenderTime += leaf.getContent().getProportionalRenderingTime();
|