js-draw 1.21.3 → 1.23.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +104 -76
- 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.d.ts +1 -3
- package/dist/cjs/Editor.js +38 -26
- package/dist/cjs/EventDispatcher.js +1 -1
- package/dist/cjs/Pointer.js +3 -3
- package/dist/cjs/SVGLoader/SVGLoader.js +15 -6
- package/dist/cjs/UndoRedoHistory.js +1 -1
- package/dist/cjs/Viewport.d.ts +1 -1
- package/dist/cjs/Viewport.js +5 -3
- 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 +2 -2
- package/dist/cjs/components/AbstractComponent.js +4 -4
- 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.d.ts +30 -7
- package/dist/cjs/image/EditorImage.js +43 -22
- 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.d.ts +2 -25
- package/dist/cjs/rendering/renderers/CanvasRenderer.js +6 -28
- package/dist/cjs/rendering/renderers/DummyRenderer.js +1 -1
- package/dist/cjs/rendering/renderers/SVGRenderer.js +39 -21
- 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.d.ts +19 -0
- package/dist/cjs/toolbar/AbstractToolbar.js +26 -11
- package/dist/cjs/toolbar/EdgeToolbar.js +11 -15
- package/dist/cjs/toolbar/IconProvider.d.ts +5 -1
- package/dist/cjs/toolbar/IconProvider.js +117 -149
- package/dist/cjs/toolbar/localization.js +5 -5
- 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.d.ts +1 -1
- package/dist/cjs/toolbar/widgets/BaseWidget.js +8 -8
- 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 +18 -13
- package/dist/cjs/tools/PasteHandler.js +8 -2
- package/dist/cjs/tools/Pen.d.ts +13 -0
- package/dist/cjs/tools/Pen.js +30 -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/lib.d.ts +1 -0
- package/dist/cjs/tools/lib.js +3 -1
- 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/cloneElementWithStyles.js +1 -1
- package/dist/cjs/util/createElement.d.ts +62 -0
- package/dist/cjs/util/createElement.js +53 -0
- 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.d.ts +1 -3
- package/dist/mjs/Editor.mjs +39 -27
- package/dist/mjs/EventDispatcher.mjs +1 -1
- package/dist/mjs/Pointer.mjs +3 -3
- package/dist/mjs/SVGLoader/SVGLoader.mjs +16 -7
- package/dist/mjs/UndoRedoHistory.mjs +1 -1
- package/dist/mjs/Viewport.d.ts +1 -1
- package/dist/mjs/Viewport.mjs +5 -3
- 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 +2 -2
- package/dist/mjs/components/AbstractComponent.mjs +4 -4
- 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.d.ts +30 -7
- package/dist/mjs/image/EditorImage.mjs +43 -22
- 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.d.ts +2 -25
- package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +6 -28
- package/dist/mjs/rendering/renderers/DummyRenderer.mjs +1 -1
- package/dist/mjs/rendering/renderers/SVGRenderer.mjs +40 -22
- 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.d.ts +19 -0
- package/dist/mjs/toolbar/AbstractToolbar.mjs +26 -11
- package/dist/mjs/toolbar/EdgeToolbar.mjs +11 -15
- package/dist/mjs/toolbar/IconProvider.d.ts +5 -1
- package/dist/mjs/toolbar/IconProvider.mjs +117 -149
- package/dist/mjs/toolbar/localization.mjs +5 -5
- 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.d.ts +1 -1
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +9 -9
- 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 +19 -14
- package/dist/mjs/tools/PasteHandler.mjs +8 -2
- package/dist/mjs/tools/Pen.d.ts +13 -0
- package/dist/mjs/tools/Pen.mjs +31 -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/lib.d.ts +1 -0
- package/dist/mjs/tools/lib.mjs +1 -0
- 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/cloneElementWithStyles.mjs +1 -1
- package/dist/mjs/util/createElement.d.ts +62 -0
- package/dist/mjs/util/createElement.mjs +47 -0
- 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
@@ -51,7 +51,20 @@ var EditorImageEventType;
|
|
51
51
|
})(EditorImageEventType || (exports.EditorImageEventType = EditorImageEventType = {}));
|
52
52
|
let debugMode = false;
|
53
53
|
/**
|
54
|
-
* Handles lookup/storage of elements in the image.
|
54
|
+
* @summary Handles lookup/storage of elements in the image.
|
55
|
+
*
|
56
|
+
* `js-draw` images are made up of a collection of {@link AbstractComponent}s (which
|
57
|
+
* includes {@link Stroke}s, {@link TextComponent}s, etc.). An `EditorImage`
|
58
|
+
* is the data structure that stores these components.
|
59
|
+
*
|
60
|
+
* Here's how to do a few common operations:
|
61
|
+
* - **Get all components in a {@link @js-draw/math!Rect2 | Rect2}**:
|
62
|
+
* {@link EditorImage.getElementsIntersectingRegion}.
|
63
|
+
* - **Draw an `EditorImage` onto a canvas/SVG**: {@link EditorImage.render}.
|
64
|
+
* - **Adding a new component**: {@link EditorImage.addElement}.
|
65
|
+
*
|
66
|
+
* **Example**:
|
67
|
+
* [[include:doc-pages/inline-examples/image-add-and-lookup.md]]
|
55
68
|
*/
|
56
69
|
class EditorImage {
|
57
70
|
// @internal
|
@@ -110,10 +123,13 @@ class EditorImage {
|
|
110
123
|
}
|
111
124
|
}
|
112
125
|
/**
|
113
|
-
* Renders
|
126
|
+
* Renders this image to the given `renderer`.
|
114
127
|
*
|
115
|
-
* `viewport` is
|
116
|
-
*
|
128
|
+
* If `viewport` is non-null, only components that can be seen from that viewport
|
129
|
+
* will be rendered. If `viewport` is `null`, **all** components are rendered.
|
130
|
+
*
|
131
|
+
* **Example**:
|
132
|
+
* [[include:doc-pages/inline-examples/canvas-renderer.md]]
|
117
133
|
*/
|
118
134
|
render(renderer, viewport) {
|
119
135
|
this.background.render(renderer, viewport?.visibleRect);
|
@@ -144,27 +160,34 @@ class EditorImage {
|
|
144
160
|
this.render(renderer, null);
|
145
161
|
}
|
146
162
|
/**
|
147
|
-
* @returns all elements in the image, sorted by z-index
|
163
|
+
* @returns all elements in the image, sorted by z-index (low to high).
|
148
164
|
*
|
149
|
-
*
|
165
|
+
* This can be slow for large images. If you only need all elemenst in part of the image,
|
166
|
+
* consider using {@link getElementsIntersectingRegion} instead.
|
167
|
+
*
|
168
|
+
* **Note**: The result does not include background elements. See {@link getBackgroundComponents}.
|
150
169
|
*/
|
151
170
|
getAllElements() {
|
152
171
|
const leaves = this.root.getLeaves();
|
153
172
|
(0, exports.sortLeavesByZIndex)(leaves);
|
154
|
-
return leaves.map(leaf => leaf.getContent());
|
173
|
+
return leaves.map((leaf) => leaf.getContent());
|
155
174
|
}
|
156
175
|
/** Returns the number of elements added to this image. @internal */
|
157
176
|
estimateNumElements() {
|
158
177
|
return this.componentCount;
|
159
178
|
}
|
160
|
-
/**
|
179
|
+
/**
|
180
|
+
* @returns a list of `AbstractComponent`s intersecting `region`, sorted by increasing z-index.
|
181
|
+
*
|
182
|
+
* Components in the background layer are only included if `includeBackground` is `true`.
|
183
|
+
*/
|
161
184
|
getElementsIntersectingRegion(region, includeBackground = false) {
|
162
185
|
let leaves = this.root.getLeavesIntersectingRegion(region);
|
163
186
|
if (includeBackground) {
|
164
187
|
leaves = leaves.concat(this.background.getLeavesIntersectingRegion(region));
|
165
188
|
}
|
166
189
|
(0, exports.sortLeavesByZIndex)(leaves);
|
167
|
-
return leaves.map(leaf => leaf.getContent());
|
190
|
+
return leaves.map((leaf) => leaf.getContent());
|
168
191
|
}
|
169
192
|
/** Called whenever (just after) an element is completely removed. @internal */
|
170
193
|
onDestroyElement(elem) {
|
@@ -504,8 +527,8 @@ const computeFirstIndexToRender = (sortedLeaves, visibleRect) => {
|
|
504
527
|
for (let i = sortedLeaves.length - 1; i >= 1; i--) {
|
505
528
|
if (
|
506
529
|
// Check for occlusion
|
507
|
-
sortedLeaves[i].getBBox().containsRect(visibleRect)
|
508
|
-
|
530
|
+
sortedLeaves[i].getBBox().containsRect(visibleRect) &&
|
531
|
+
sortedLeaves[i].getContent()?.occludesEverythingBelowWhenRenderedInRect(visibleRect)) {
|
509
532
|
startIndex = i;
|
510
533
|
break;
|
511
534
|
}
|
@@ -541,7 +564,7 @@ class ImageNode {
|
|
541
564
|
}
|
542
565
|
// Override this to change how children are considered within a given region.
|
543
566
|
getChildrenIntersectingRegion(region, isTooSmallFilter) {
|
544
|
-
return this.children.filter(child => {
|
567
|
+
return this.children.filter((child) => {
|
545
568
|
const bbox = child.getBBox();
|
546
569
|
return !isTooSmallFilter?.(bbox) && bbox.intersects(region);
|
547
570
|
});
|
@@ -632,7 +655,7 @@ class ImageNode {
|
|
632
655
|
}
|
633
656
|
return nodeForNewLeaf.addLeaf(leaf);
|
634
657
|
}
|
635
|
-
const containingNodes = this.children.filter(child => child.getBBox().containsRect(leafBBox));
|
658
|
+
const containingNodes = this.children.filter((child) => child.getBBox().containsRect(leafBBox));
|
636
659
|
// Does the leaf already fit within one of the children?
|
637
660
|
if (containingNodes.length > 0 && this.children.length >= this.targetChildCount) {
|
638
661
|
// Sort the containers in ascending order by area
|
@@ -670,7 +693,7 @@ class ImageNode {
|
|
670
693
|
this.bbox = this.content.getBBox();
|
671
694
|
}
|
672
695
|
else {
|
673
|
-
this.bbox = math_1.Rect2.union(...this.children.map(child => child.getBBox()));
|
696
|
+
this.bbox = math_1.Rect2.union(...this.children.map((child) => child.getBBox()));
|
674
697
|
}
|
675
698
|
if (bubbleUp && !oldBBox.eq(this.bbox)) {
|
676
699
|
if (this.bbox.containsRect(oldBBox)) {
|
@@ -705,7 +728,7 @@ class ImageNode {
|
|
705
728
|
const oldParent = this.parent;
|
706
729
|
if (oldParent.parent !== null) {
|
707
730
|
const newParent = oldParent.parent;
|
708
|
-
newParent.children = newParent.children.filter(c => c !== oldParent);
|
731
|
+
newParent.children = newParent.children.filter((c) => c !== oldParent);
|
709
732
|
oldParent.parent = null;
|
710
733
|
oldParent.children = [];
|
711
734
|
this.parent = newParent;
|
@@ -777,11 +800,11 @@ class ImageNode {
|
|
777
800
|
removeChild(child) {
|
778
801
|
this.checkRep();
|
779
802
|
const oldChildCount = this.children.length;
|
780
|
-
this.children = this.children.filter(node => {
|
803
|
+
this.children = this.children.filter((node) => {
|
781
804
|
return node !== child;
|
782
805
|
});
|
783
806
|
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.`);
|
784
|
-
this.children.forEach(child => {
|
807
|
+
this.children.forEach((child) => {
|
785
808
|
child.rebalance();
|
786
809
|
});
|
787
810
|
this.recomputeBBox(true);
|
@@ -830,7 +853,7 @@ class ImageNode {
|
|
830
853
|
render(renderer, visibleRect) {
|
831
854
|
let leaves;
|
832
855
|
if (visibleRect) {
|
833
|
-
leaves = this.getLeavesIntersectingRegion(visibleRect, rect => renderer.isTooSmallToRender(rect));
|
856
|
+
leaves = this.getLeavesIntersectingRegion(visibleRect, (rect) => renderer.isTooSmallToRender(rect));
|
834
857
|
}
|
835
858
|
else {
|
836
859
|
leaves = this.getLeaves();
|
@@ -941,10 +964,8 @@ class RootImageNode extends ImageNode {
|
|
941
964
|
};
|
942
965
|
// Check whether the child is stored in the data/fullscreen
|
943
966
|
// component arrays first.
|
944
|
-
this.dataComponents = this.dataComponents
|
945
|
-
|
946
|
-
this.fullscreenChildren = this.fullscreenChildren
|
947
|
-
.filter(checkTargetChild);
|
967
|
+
this.dataComponents = this.dataComponents.filter(checkTargetChild);
|
968
|
+
this.fullscreenChildren = this.fullscreenChildren.filter(checkTargetChild);
|
948
969
|
if (!removed) {
|
949
970
|
super.removeChild(child);
|
950
971
|
}
|
@@ -52,7 +52,7 @@ const editorImageToSVGSync = (image, options) => {
|
|
52
52
|
};
|
53
53
|
exports.editorImageToSVGSync = editorImageToSVGSync;
|
54
54
|
const editorImageToSVGAsync = (image, preRenderComponent, options) => {
|
55
|
-
return new Promise(resolve => {
|
55
|
+
return new Promise((resolve) => {
|
56
56
|
toSVGInternal(image, async (renderer, onComplete) => {
|
57
57
|
await image.renderAllAsync(renderer, preRenderComponent);
|
58
58
|
const result = onComplete();
|
package/dist/cjs/inputEvents.js
CHANGED
@@ -34,8 +34,8 @@ const keyPressEventFromHTMLEvent = (event) => {
|
|
34
34
|
};
|
35
35
|
exports.keyPressEventFromHTMLEvent = keyPressEventFromHTMLEvent;
|
36
36
|
const isPointerEvt = (event) => {
|
37
|
-
return event.kind === InputEvtType.PointerDownEvt
|
38
|
-
|
39
|
-
|
37
|
+
return (event.kind === InputEvtType.PointerDownEvt ||
|
38
|
+
event.kind === InputEvtType.PointerMoveEvt ||
|
39
|
+
event.kind === InputEvtType.PointerUpEvt);
|
40
40
|
};
|
41
41
|
exports.isPointerEvt = isPointerEvt;
|
package/dist/cjs/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.
|
@@ -91,11 +91,11 @@ const localization = {
|
|
91
91
|
textNodeCount: (count) => `Es gibt ${count} sichtbare Text-Knotenpunkte.`,
|
92
92
|
textNode: (content) => `Text: ${content}`,
|
93
93
|
imageNodeCount: (nodeCount) => `Es gibt ${nodeCount} sichtbare Bild-Knoten.`,
|
94
|
-
imageNode: label => `Bild: ${label}`,
|
94
|
+
imageNode: (label) => `Bild: ${label}`,
|
95
95
|
unlabeledImageNode: 'Bild ohne Label',
|
96
96
|
rerenderAsText: 'Als Text darstellen',
|
97
97
|
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.',
|
98
|
-
loading: percentage => `Laden ${percentage}%...`,
|
98
|
+
loading: (percentage) => `Laden ${percentage}%...`,
|
99
99
|
doneLoading: 'Laden fertig',
|
100
100
|
imageEditor: 'Bild-Editor',
|
101
101
|
undoAnnouncement: (commandDescription) => `${commandDescription} rückgängig gemacht`,
|
@@ -48,9 +48,13 @@ const localization = {
|
|
48
48
|
selectionMenu__duplicate: 'Duplicar',
|
49
49
|
closeSidebar: (toolName) => `Close sidebar for ${toolName}`,
|
50
50
|
dropdownShown: (toolName) => `Menú por ${toolName} es visible`,
|
51
|
-
dropdownHidden: (toolName) => {
|
51
|
+
dropdownHidden: (toolName) => {
|
52
|
+
return `Menú por ${toolName} fue ocultado`;
|
53
|
+
},
|
52
54
|
zoomLevel: (zoomPercent) => `Zoom: ${zoomPercent}%`,
|
53
|
-
colorChangedAnnouncement: (color) => {
|
55
|
+
colorChangedAnnouncement: (color) => {
|
56
|
+
return `Color fue cambiado a ${color}`;
|
57
|
+
},
|
54
58
|
imageSize: (size, units) => `Tamaño del imagen: ${size} ${units}`,
|
55
59
|
imageLoadError: (message) => `Error cargando imagen: ${message}`,
|
56
60
|
penTool: (penId) => `Lapiz ${penId}`,
|
@@ -67,7 +71,7 @@ const localization = {
|
|
67
71
|
closeDialog: 'Cerrar',
|
68
72
|
anyDevicePanning: 'Mover la pantalla con todo dispotivo',
|
69
73
|
copied: (count) => `${count} cosas fueron copiados`,
|
70
|
-
pasted: (count) => count === 1 ? 'Pegado' : `${count} cosas fueron pegados
|
74
|
+
pasted: (count) => (count === 1 ? 'Pegado' : `${count} cosas fueron pegados`),
|
71
75
|
toolEnabledAnnouncement: (toolName) => `${toolName} fue activado`,
|
72
76
|
toolDisabledAnnouncement: (toolName) => `${toolName} fue desactivado`,
|
73
77
|
resizeOutputCommand: (newSize) => `Tamaño de imagen fue cambiado a ${newSize.w}x${newSize.h}`,
|
@@ -85,7 +85,7 @@ class Display {
|
|
85
85
|
// Require about 105 strokes with 4 parts each to use the cache at all.
|
86
86
|
minProportionalRenderTimeToUseCache: 105 * 4,
|
87
87
|
});
|
88
|
-
this.editor.notifier.on(types_1.EditorEventType.DisplayResized, event => {
|
88
|
+
this.editor.notifier.on(types_1.EditorEventType.DisplayResized, (event) => {
|
89
89
|
if (event.kind !== types_1.EditorEventType.DisplayResized) {
|
90
90
|
throw new Error('Mismatched event.kinds!');
|
91
91
|
}
|
@@ -123,10 +123,14 @@ class Display {
|
|
123
123
|
}
|
124
124
|
this.resizeSurfacesCallback = () => {
|
125
125
|
const expectedWidth = (canvas) => {
|
126
|
-
|
126
|
+
const widthInPixels = Math.ceil(canvas.clientWidth * this.devicePixelRatio);
|
127
|
+
// Avoid setting the canvas width to zero -- doing so can cause errors when attempting
|
128
|
+
// to use the canvas:
|
129
|
+
return widthInPixels || canvas.width;
|
127
130
|
};
|
128
131
|
const expectedHeight = (canvas) => {
|
129
|
-
|
132
|
+
const heightInPixels = Math.ceil(canvas.clientHeight * this.devicePixelRatio);
|
133
|
+
return heightInPixels || canvas.height; // Zero-size canvases can cause errors.
|
130
134
|
};
|
131
135
|
const hasSizeMismatch = (canvas) => {
|
132
136
|
return expectedHeight(canvas) !== canvas.height || expectedWidth(canvas) !== canvas.width;
|
@@ -42,15 +42,18 @@ const pathIncluded = (renderablePath, path) => {
|
|
42
42
|
*
|
43
43
|
* @internal
|
44
44
|
*/
|
45
|
-
const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, options = {
|
45
|
+
const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, options = {
|
46
|
+
fastCheck: true,
|
47
|
+
expensiveCheck: true,
|
48
|
+
}) => {
|
46
49
|
const path = (0, exports.pathFromRenderable)(renderablePath);
|
47
50
|
const strokeWidth = renderablePath.style.stroke?.width ?? 0;
|
48
51
|
const onlyStroked = strokeWidth > 0 && renderablePath.style.fill.a === 0;
|
49
52
|
const styledPathBBox = path.bbox.grownBy(strokeWidth);
|
50
53
|
// Are we close enough to the path that it fills the entire screen?
|
51
|
-
const isOnlyStrokedAndCouldFillScreen =
|
52
|
-
|
53
|
-
|
54
|
+
const isOnlyStrokedAndCouldFillScreen = onlyStroked &&
|
55
|
+
strokeWidth > visibleRect.maxDimension &&
|
56
|
+
styledPathBBox.containsRect(visibleRect);
|
54
57
|
if (options.fastCheck && isOnlyStrokedAndCouldFillScreen && renderablePath.style.stroke) {
|
55
58
|
const strokeRadius = strokeWidth / 2;
|
56
59
|
// Are we completely within the stroke?
|
@@ -60,7 +63,9 @@ const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, options =
|
|
60
63
|
if (visibleRect.isWithinRadiusOf(strokeRadius, point)) {
|
61
64
|
return {
|
62
65
|
rectangle: visibleRect,
|
63
|
-
path: (0, exports.pathToRenderable)(math_1.Path.fromRect(visibleRect), {
|
66
|
+
path: (0, exports.pathToRenderable)(math_1.Path.fromRect(visibleRect), {
|
67
|
+
fill: renderablePath.style.stroke.color,
|
68
|
+
}),
|
64
69
|
fullScreen: true,
|
65
70
|
};
|
66
71
|
}
|
@@ -68,13 +73,16 @@ const simplifyPathToFullScreenOrEmpty = (renderablePath, visibleRect, options =
|
|
68
73
|
}
|
69
74
|
// Try filtering again, but with slightly more expensive checks
|
70
75
|
if (options.expensiveCheck &&
|
71
|
-
isOnlyStrokedAndCouldFillScreen &&
|
72
|
-
|
76
|
+
isOnlyStrokedAndCouldFillScreen &&
|
77
|
+
renderablePath.style.stroke &&
|
78
|
+
strokeWidth > visibleRect.maxDimension * 3) {
|
73
79
|
const signedDist = path.signedDistance(visibleRect.center, strokeWidth / 2);
|
74
80
|
const margin = strokeWidth / 6;
|
75
81
|
if (signedDist < -visibleRect.maxDimension / 2 - margin) {
|
76
82
|
return {
|
77
|
-
path: (0, exports.pathToRenderable)(math_1.Path.fromRect(visibleRect), {
|
83
|
+
path: (0, exports.pathToRenderable)(math_1.Path.fromRect(visibleRect), {
|
84
|
+
fill: renderablePath.style.stroke.color,
|
85
|
+
}),
|
78
86
|
rectangle: visibleRect,
|
79
87
|
fullScreen: true,
|
80
88
|
};
|
@@ -98,12 +106,16 @@ const visualEquivalent = (renderablePath, visibleRect) => {
|
|
98
106
|
const strokeWidth = renderablePath.style.stroke?.width ?? 0;
|
99
107
|
const onlyStroked = strokeWidth > 0 && renderablePath.style.fill.a === 0;
|
100
108
|
const styledPathBBox = path.bbox.grownBy(strokeWidth);
|
101
|
-
let rectangleSimplification = (0, exports.simplifyPathToFullScreenOrEmpty)(renderablePath, visibleRect, {
|
109
|
+
let rectangleSimplification = (0, exports.simplifyPathToFullScreenOrEmpty)(renderablePath, visibleRect, {
|
110
|
+
fastCheck: true,
|
111
|
+
expensiveCheck: false,
|
112
|
+
});
|
102
113
|
if (rectangleSimplification) {
|
103
114
|
return rectangleSimplification.path;
|
104
115
|
}
|
105
116
|
// Scale the expanded rect --- the visual equivalent is only close for huge strokes.
|
106
|
-
const expandedRect = visibleRect
|
117
|
+
const expandedRect = visibleRect
|
118
|
+
.grownBy(strokeWidth)
|
107
119
|
.transformedBoundingBox(math_1.Mat33.scaling2D(4, visibleRect.center));
|
108
120
|
// TODO: Handle simplifying very small paths.
|
109
121
|
if (expandedRect.containsRect(styledPathBBox)) {
|
@@ -144,7 +156,10 @@ const visualEquivalent = (renderablePath, visibleRect) => {
|
|
144
156
|
}
|
145
157
|
const newPath = new math_1.Path(path.startPoint, parts);
|
146
158
|
const newStyle = renderablePath.style;
|
147
|
-
rectangleSimplification = (0, exports.simplifyPathToFullScreenOrEmpty)(renderablePath, visibleRect, {
|
159
|
+
rectangleSimplification = (0, exports.simplifyPathToFullScreenOrEmpty)(renderablePath, visibleRect, {
|
160
|
+
fastCheck: false,
|
161
|
+
expensiveCheck: true,
|
162
|
+
});
|
148
163
|
if (rectangleSimplification) {
|
149
164
|
return rectangleSimplification.path;
|
150
165
|
}
|
@@ -5,17 +5,20 @@ const math_1 = require("@js-draw/math");
|
|
5
5
|
const cloneStyle = (style) => {
|
6
6
|
return {
|
7
7
|
fill: style.fill,
|
8
|
-
stroke: style.stroke
|
9
|
-
|
10
|
-
|
8
|
+
stroke: style.stroke
|
9
|
+
? {
|
10
|
+
...style.stroke,
|
11
|
+
}
|
12
|
+
: undefined,
|
11
13
|
};
|
12
14
|
};
|
13
15
|
exports.cloneStyle = cloneStyle;
|
14
16
|
const stylesEqual = (a, b) => {
|
15
|
-
const result = a === b ||
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
const result = a === b ||
|
18
|
+
(a.fill.eq(b.fill) &&
|
19
|
+
(a.stroke == undefined) === (b.stroke == undefined) &&
|
20
|
+
(a.stroke?.color?.eq(b.stroke?.color) ?? true) &&
|
21
|
+
a.stroke?.width === b.stroke?.width);
|
19
22
|
// Map undefined/null -> false
|
20
23
|
return result ?? false;
|
21
24
|
};
|
@@ -23,10 +26,12 @@ exports.stylesEqual = stylesEqual;
|
|
23
26
|
// Returns an object that can be converted to a JSON string with
|
24
27
|
// JSON.stringify.
|
25
28
|
const styleToJSON = (style) => {
|
26
|
-
const stroke = !style.stroke
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
const stroke = !style.stroke
|
30
|
+
? undefined
|
31
|
+
: {
|
32
|
+
color: style.stroke.color.toHexString(),
|
33
|
+
width: style.stroke.width,
|
34
|
+
};
|
30
35
|
return {
|
31
36
|
fill: style.fill.toHexString(),
|
32
37
|
stroke,
|
@@ -34,10 +39,12 @@ const styleToJSON = (style) => {
|
|
34
39
|
};
|
35
40
|
exports.styleToJSON = styleToJSON;
|
36
41
|
const styleFromJSON = (json) => {
|
37
|
-
const stroke = json.stroke
|
38
|
-
|
39
|
-
|
40
|
-
|
42
|
+
const stroke = json.stroke
|
43
|
+
? {
|
44
|
+
color: math_1.Color4.fromHex(json.stroke.color),
|
45
|
+
width: json.stroke.width,
|
46
|
+
}
|
47
|
+
: undefined;
|
41
48
|
return {
|
42
49
|
fill: math_1.Color4.fromHex(json.fill),
|
43
50
|
stroke,
|
@@ -14,7 +14,7 @@ const textStyleFromJSON = (json) => {
|
|
14
14
|
if (typeof json === 'string') {
|
15
15
|
json = JSON.parse(json);
|
16
16
|
}
|
17
|
-
if (typeof
|
17
|
+
if (typeof json.fontFamily !== 'string') {
|
18
18
|
throw new Error('Serialized textStyle missing string fontFamily attribute!');
|
19
19
|
}
|
20
20
|
const style = {
|
@@ -17,7 +17,7 @@ class CacheRecord {
|
|
17
17
|
startRender() {
|
18
18
|
this.lastUsedCycle = this.cacheState.currentRenderingCycle;
|
19
19
|
if (!this.allocd) {
|
20
|
-
throw new Error(
|
20
|
+
throw new Error("Only alloc'd canvases can be rendered to");
|
21
21
|
}
|
22
22
|
return this.renderer;
|
23
23
|
}
|
@@ -34,7 +34,7 @@ class CacheRecordManager {
|
|
34
34
|
lru.realloc(onDealloc);
|
35
35
|
lru.setRenderingRegion(drawTo);
|
36
36
|
if (this.cacheState.debugMode) {
|
37
|
-
console.log(
|
37
|
+
console.log("[Cache] Now re-alloc'd. Last used cycle: ", lru.getLastUsedCycle());
|
38
38
|
console.assert(lru['cacheState'] === this.cacheState, '[Cache] Unequal cache states! cacheState should be a shared object!');
|
39
39
|
}
|
40
40
|
return lru;
|
@@ -35,7 +35,7 @@ class RenderingCache {
|
|
35
35
|
this.rootNode = this.rootNode.generateParent();
|
36
36
|
}
|
37
37
|
this.rootNode = this.rootNode.smallestChildContaining(visibleRect) ?? this.rootNode;
|
38
|
-
const visibleLeaves = image.getLeavesIntersectingRegion(viewport.visibleRect, rect => screenRenderer.isTooSmallToRender(rect));
|
38
|
+
const visibleLeaves = image.getLeavesIntersectingRegion(viewport.visibleRect, (rect) => screenRenderer.isTooSmallToRender(rect));
|
39
39
|
let approxVisibleRenderTime = 0;
|
40
40
|
for (const leaf of visibleLeaves) {
|
41
41
|
approxVisibleRenderTime += leaf.getContent().getProportionalRenderingTime();
|
@@ -32,7 +32,7 @@ class RenderingCacheNode {
|
|
32
32
|
const middleChildIdx = (parent.instantiatedChildren.length - 1) / 2;
|
33
33
|
if (!parent.instantiatedChildren[middleChildIdx].region.eq(this.region, checkTolerance)) {
|
34
34
|
console.error(parent.instantiatedChildren[middleChildIdx].region, '≠', this.region);
|
35
|
-
throw new Error(
|
35
|
+
throw new Error("Logic error: [this] is not contained within its parent's center child");
|
36
36
|
}
|
37
37
|
// Replace the middle child
|
38
38
|
parent.instantiatedChildren[middleChildIdx] = this;
|
@@ -42,7 +42,8 @@ class RenderingCacheNode {
|
|
42
42
|
// Generates children, if missing.
|
43
43
|
generateChildren() {
|
44
44
|
if (this.instantiatedChildren.length === 0) {
|
45
|
-
if (this.region.size.x / cacheDivisionSize === 0 ||
|
45
|
+
if (this.region.size.x / cacheDivisionSize === 0 ||
|
46
|
+
this.region.size.y / cacheDivisionSize === 0) {
|
46
47
|
console.warn('Cache element has zero size! Not generating children.');
|
47
48
|
return;
|
48
49
|
}
|
@@ -137,8 +138,7 @@ class RenderingCacheNode {
|
|
137
138
|
}
|
138
139
|
// Render all [items] within [viewport]
|
139
140
|
renderItems(screenRenderer, items, viewport) {
|
140
|
-
if (!viewport.visibleRect.intersects(this.region)
|
141
|
-
|| items.length === 0) {
|
141
|
+
if (!viewport.visibleRect.intersects(this.region) || items.length === 0) {
|
142
142
|
return;
|
143
143
|
}
|
144
144
|
// Divide [items] until nodes are smaller than this, or are leaves.
|
@@ -167,13 +167,15 @@ class RenderingCacheNode {
|
|
167
167
|
return;
|
168
168
|
}
|
169
169
|
if (this.cacheState.debugMode) {
|
170
|
-
screenRenderer.drawRect(this.region, viewport.getSizeOfPixelOnCanvas(), {
|
170
|
+
screenRenderer.drawRect(this.region, viewport.getSizeOfPixelOnCanvas(), {
|
171
|
+
fill: math_1.Color4.yellow,
|
172
|
+
});
|
171
173
|
}
|
172
174
|
// Could we render direclty from [this] or do we need to recurse?
|
173
175
|
const couldRender = this.renderingWouldBeHighEnoughResolution(viewport);
|
174
176
|
if (!couldRender) {
|
175
177
|
for (const child of this.getChildren()) {
|
176
|
-
child.renderItems(screenRenderer, items.filter(item => {
|
178
|
+
child.renderItems(screenRenderer, items.filter((item) => {
|
177
179
|
return item.getBBox().intersects(child.region);
|
178
180
|
}), viewport);
|
179
181
|
}
|
@@ -191,7 +193,7 @@ class RenderingCacheNode {
|
|
191
193
|
if (leavesByIds.length === 0) {
|
192
194
|
return;
|
193
195
|
}
|
194
|
-
const leafIds = leavesByIds.map(leaf => leaf.getId());
|
196
|
+
const leafIds = leavesByIds.map((leaf) => leaf.getId());
|
195
197
|
let thisRenderer;
|
196
198
|
if (!this.renderingIsUpToDate(leafIds)) {
|
197
199
|
if (this.allChildrenCanRender(viewport, leavesByIds)) {
|
@@ -212,7 +214,9 @@ class RenderingCacheNode {
|
|
212
214
|
if (!this.cachedRenderer) {
|
213
215
|
this.cachedRenderer = this.cacheState.recordManager.allocCanvas(this.region, () => this.onRegionDealloc());
|
214
216
|
}
|
215
|
-
else if (leavesByIds.length > this.renderedIds.length &&
|
217
|
+
else if (leavesByIds.length > this.renderedIds.length &&
|
218
|
+
this.allRenderedIdsIn(leafIds) &&
|
219
|
+
this.renderedMaxZIndex !== null) {
|
216
220
|
// We often don't need to do a full re-render even if something's changed.
|
217
221
|
// Check whether we can just draw on top of the existing cache.
|
218
222
|
const newLeaves = [];
|
@@ -242,7 +246,9 @@ class RenderingCacheNode {
|
|
242
246
|
}
|
243
247
|
if (this.cacheState.debugMode) {
|
244
248
|
// Clay for adding new elements
|
245
|
-
screenRenderer.drawRect(this.region, 2 * viewport.getSizeOfPixelOnCanvas(), {
|
249
|
+
screenRenderer.drawRect(this.region, 2 * viewport.getSizeOfPixelOnCanvas(), {
|
250
|
+
fill: math_1.Color4.clay,
|
251
|
+
});
|
246
252
|
}
|
247
253
|
}
|
248
254
|
}
|
@@ -263,7 +269,9 @@ class RenderingCacheNode {
|
|
263
269
|
}
|
264
270
|
if (this.cacheState.debugMode) {
|
265
271
|
// Red for full rerender
|
266
|
-
screenRenderer.drawRect(this.region, 3 * viewport.getSizeOfPixelOnCanvas(), {
|
272
|
+
screenRenderer.drawRect(this.region, 3 * viewport.getSizeOfPixelOnCanvas(), {
|
273
|
+
fill: math_1.Color4.red,
|
274
|
+
});
|
267
275
|
}
|
268
276
|
}
|
269
277
|
this.renderedIds = leafIds;
|
@@ -282,7 +290,9 @@ class RenderingCacheNode {
|
|
282
290
|
screenRenderer.endObject();
|
283
291
|
if (this.cacheState.debugMode) {
|
284
292
|
// Green for no cache needed render
|
285
|
-
screenRenderer.drawRect(this.region, 2 * viewport.getSizeOfPixelOnCanvas(), {
|
293
|
+
screenRenderer.drawRect(this.region, 2 * viewport.getSizeOfPixelOnCanvas(), {
|
294
|
+
fill: math_1.Color4.green,
|
295
|
+
});
|
286
296
|
}
|
287
297
|
}
|
288
298
|
}
|
@@ -294,7 +304,7 @@ class RenderingCacheNode {
|
|
294
304
|
screenRenderer.renderFromOtherOfSameType(transformMat, thisRenderer);
|
295
305
|
}
|
296
306
|
// Can we clean up this' children? (Are they unused?)
|
297
|
-
if (this.instantiatedChildren.every(child => child.isEmpty())) {
|
307
|
+
if (this.instantiatedChildren.every((child) => child.isEmpty())) {
|
298
308
|
this.instantiatedChildren = [];
|
299
309
|
}
|
300
310
|
}
|
@@ -305,7 +315,7 @@ class RenderingCacheNode {
|
|
305
315
|
if (this.cachedRenderer !== null) {
|
306
316
|
return false;
|
307
317
|
}
|
308
|
-
return this.instantiatedChildren.every(child => child.isEmpty());
|
318
|
+
return this.instantiatedChildren.every((child) => child.isEmpty());
|
309
319
|
}
|
310
320
|
onRegionDealloc() {
|
311
321
|
this.cachedRenderer = null;
|
@@ -314,7 +324,8 @@ class RenderingCacheNode {
|
|
314
324
|
}
|
315
325
|
}
|
316
326
|
checkRep() {
|
317
|
-
if (this.instantiatedChildren.length !== cacheDivisionSize * cacheDivisionSize &&
|
327
|
+
if (this.instantiatedChildren.length !== cacheDivisionSize * cacheDivisionSize &&
|
328
|
+
this.instantiatedChildren.length !== 0) {
|
318
329
|
throw new Error(`Repcheck: Wrong number of children. Got ${this.instantiatedChildren.length}`);
|
319
330
|
}
|
320
331
|
if (this.renderedIds[1] !== undefined && this.renderedIds[0] >= this.renderedIds[1]) {
|
@@ -327,7 +338,7 @@ class RenderingCacheNode {
|
|
327
338
|
}
|
328
339
|
}
|
329
340
|
if (this.cachedRenderer && !this.cachedRenderer.isAllocd()) {
|
330
|
-
throw new Error(
|
341
|
+
throw new Error("this' cachedRenderer != null, but is dealloc'd");
|
331
342
|
}
|
332
343
|
}
|
333
344
|
}
|
@@ -25,11 +25,11 @@ const createCache = (onRenderAlloc, cacheOptions) => {
|
|
25
25
|
maxScale: 2,
|
26
26
|
minProportionalRenderTimePerCache: 0,
|
27
27
|
minProportionalRenderTimeToUseCache: 0,
|
28
|
-
...cacheOptions
|
28
|
+
...cacheOptions,
|
29
29
|
});
|
30
30
|
return {
|
31
31
|
cache,
|
32
|
-
editor
|
32
|
+
editor,
|
33
33
|
};
|
34
34
|
};
|
35
35
|
exports.createCache = createCache;
|
@@ -22,7 +22,9 @@ class AbstractRenderer {
|
|
22
22
|
* methods on `Viewport`, because the viewport may not accurately reflect
|
23
23
|
* what is rendered.
|
24
24
|
*/
|
25
|
-
getViewport() {
|
25
|
+
getViewport() {
|
26
|
+
return this.viewport;
|
27
|
+
}
|
26
28
|
setDraftMode(_draftMode) { }
|
27
29
|
flushPath() {
|
28
30
|
if (!this.currentPaths) {
|
@@ -7,31 +7,8 @@ import RenderablePathSpec from '../RenderablePathSpec';
|
|
7
7
|
/**
|
8
8
|
* Renders onto a `CanvasRenderingContext2D`.
|
9
9
|
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
* import {Editor,CanvasRenderer} from 'js-draw';
|
13
|
-
*
|
14
|
-
* // Create an editor and load initial data -- don't add to the body (hidden editor).
|
15
|
-
* const editor = new Editor(document.createElement('div'));
|
16
|
-
* await editor.loadFromSVG('<svg><path d="m0,0 l100,5 l-50,60 l30,20 z" fill="green"/></svg>');
|
17
|
-
* ---visible---
|
18
|
-
* // Given some editor.
|
19
|
-
* // Set up the canvas to be drawn onto.
|
20
|
-
* const canvas = document.createElement('canvas');
|
21
|
-
* const ctx = canvas.getContext('2d');
|
22
|
-
*
|
23
|
-
* // Ensure that the canvas can fit the entire rendering
|
24
|
-
* const viewport = editor.image.getImportExportViewport();
|
25
|
-
* canvas.width = viewport.getScreenRectSize().x;
|
26
|
-
* canvas.height = viewport.getScreenRectSize().y;
|
27
|
-
*
|
28
|
-
* // Render editor.image onto the renderer
|
29
|
-
* const renderer = new CanvasRenderer(ctx, viewport);
|
30
|
-
* editor.image.render(renderer, viewport);
|
31
|
-
*
|
32
|
-
* // Add the rendered canvas to the document.
|
33
|
-
* document.body.appendChild(canvas);
|
34
|
-
* ```
|
10
|
+
* **Example**:
|
11
|
+
* [[include:doc-pages/inline-examples/canvas-renderer.md]]
|
35
12
|
*/
|
36
13
|
export default class CanvasRenderer extends AbstractRenderer {
|
37
14
|
private ctx;
|