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
@@ -1,8 +1,8 @@
|
|
1
|
-
import { Path, Rect2, PathCommandType, comparePathIndices, stepPathIndexBy } from '@js-draw/math';
|
1
|
+
import { Path, Rect2, PathCommandType, comparePathIndices, stepPathIndexBy, } from '@js-draw/math';
|
2
2
|
import { styleFromJSON, styleToJSON } from '../rendering/RenderingStyle.mjs';
|
3
3
|
import AbstractComponent from './AbstractComponent.mjs';
|
4
|
-
import { createRestyleComponentCommand } from './RestylableComponent.mjs';
|
5
|
-
import { pathFromRenderable, pathToRenderable, simplifyPathToFullScreenOrEmpty } from '../rendering/RenderablePathSpec.mjs';
|
4
|
+
import { createRestyleComponentCommand, } from './RestylableComponent.mjs';
|
5
|
+
import { pathFromRenderable, pathToRenderable, simplifyPathToFullScreenOrEmpty, } from '../rendering/RenderablePathSpec.mjs';
|
6
6
|
/**
|
7
7
|
* Represents an {@link AbstractComponent} made up of one or more {@link Path}s.
|
8
8
|
*
|
@@ -74,8 +74,7 @@ export default class Stroke extends AbstractComponent {
|
|
74
74
|
return {};
|
75
75
|
}
|
76
76
|
const firstPart = this.parts[0];
|
77
|
-
if (firstPart.style.stroke === undefined
|
78
|
-
|| firstPart.style.stroke.width === 0) {
|
77
|
+
if (firstPart.style.stroke === undefined || firstPart.style.stroke.width === 0) {
|
79
78
|
return {
|
80
79
|
color: firstPart.style.fill,
|
81
80
|
};
|
@@ -94,9 +93,11 @@ export default class Stroke extends AbstractComponent {
|
|
94
93
|
this.parts = this.parts.map((part) => {
|
95
94
|
const newStyle = {
|
96
95
|
...part.style,
|
97
|
-
stroke: part.style.stroke
|
98
|
-
|
99
|
-
|
96
|
+
stroke: part.style.stroke
|
97
|
+
? {
|
98
|
+
...part.style.stroke,
|
99
|
+
}
|
100
|
+
: undefined,
|
100
101
|
};
|
101
102
|
// Change the stroke color if a stroked shape. Else,
|
102
103
|
// change the fill.
|
@@ -131,7 +132,8 @@ export default class Stroke extends AbstractComponent {
|
|
131
132
|
const makeStroke = (path) => {
|
132
133
|
if (part.style.fill.a > 0) {
|
133
134
|
// Remove visually empty paths.
|
134
|
-
if (path.parts.length < 1 ||
|
135
|
+
if (path.parts.length < 1 ||
|
136
|
+
(path.parts.length === 1 && path.parts[0].kind === PathCommandType.LineTo)) {
|
135
137
|
// TODO: If this isn't present, a very large number of strokes are created while erasing.
|
136
138
|
return null;
|
137
139
|
}
|
@@ -164,10 +166,10 @@ export default class Stroke extends AbstractComponent {
|
|
164
166
|
// 2. If zoomed in significantly, it's unlikely that the user wants to erase a large
|
165
167
|
// part of the stroke.
|
166
168
|
let isErasingFromEdge = false;
|
167
|
-
if (intersectionPoints.length === 0
|
168
|
-
|
169
|
-
|
170
|
-
|
169
|
+
if (intersectionPoints.length === 0 &&
|
170
|
+
part.style.stroke &&
|
171
|
+
part.style.stroke.width > eraserPath.bbox.minDimension * 0.3 &&
|
172
|
+
part.style.stroke.width < eraserPath.bbox.maxDimension * 30) {
|
171
173
|
for (const segment of polyline) {
|
172
174
|
intersectionPoints.push(...path.intersection(segment, part.style.stroke.width / 2));
|
173
175
|
}
|
@@ -181,7 +183,7 @@ export default class Stroke extends AbstractComponent {
|
|
181
183
|
}
|
182
184
|
// The eraser may not be near the center of the curve -- approximate.
|
183
185
|
if (isErasingFromEdge) {
|
184
|
-
return intersectionPoints[0].curveIndex === 0 && intersectionPoints[0].parameterValue <= 0;
|
186
|
+
return (intersectionPoints[0].curveIndex === 0 && intersectionPoints[0].parameterValue <= 0);
|
185
187
|
}
|
186
188
|
const justBeforeFirstIntersection = stepPathIndexBy(intersectionPoints[0], -1e-10);
|
187
189
|
return isPointInsideEraser(path.at(justBeforeFirstIntersection));
|
@@ -198,24 +200,30 @@ export default class Stroke extends AbstractComponent {
|
|
198
200
|
// (including https://github.com/Pomax/bezierjs/issues/179).
|
199
201
|
// Even if not all intersections are returned correctly, we still want
|
200
202
|
// isInside to be roughly correct.
|
201
|
-
if (knownToBeInside === undefined &&
|
203
|
+
if (knownToBeInside === undefined &&
|
204
|
+
!isInside &&
|
205
|
+
eraserPath.closedContainsPoint(path.getExactBBox().center)) {
|
202
206
|
isInside = !isInside;
|
203
207
|
}
|
204
208
|
if (!component) {
|
205
209
|
return;
|
206
210
|
}
|
207
211
|
// Assertion: Avoid deleting sections that are much larger than the eraser.
|
208
|
-
failedAssertions ||=
|
212
|
+
failedAssertions ||=
|
213
|
+
isInside && path.getExactBBox().maxDimension > eraserPath.getExactBBox().maxDimension * 2;
|
209
214
|
if (!isInside) {
|
210
215
|
newStrokes.push(component);
|
211
216
|
}
|
212
217
|
};
|
213
|
-
if (part.style.fill.a === 0) {
|
218
|
+
if (part.style.fill.a === 0) {
|
219
|
+
// Not filled?
|
214
220
|
// An additional case where we erase completely -- without the padding of the stroke,
|
215
221
|
// the path is smaller than the eraser (allows us to erase dots completely).
|
216
222
|
const shouldEraseCompletely = eraserPath.getExactBBox().maxDimension / 10 > path.getExactBBox().maxDimension;
|
217
223
|
if (!shouldEraseCompletely) {
|
218
|
-
const split = path.splitAt(intersectionPoints, {
|
224
|
+
const split = path.splitAt(intersectionPoints, {
|
225
|
+
mapNewPoint: (p) => viewport.roundPoint(p),
|
226
|
+
});
|
219
227
|
for (const splitPart of split) {
|
220
228
|
addNewPath(splitPart);
|
221
229
|
}
|
@@ -257,7 +265,9 @@ export default class Stroke extends AbstractComponent {
|
|
257
265
|
//
|
258
266
|
// The difficulty here is correctly pairing edges to create the the output
|
259
267
|
// strokes, particularly because we don't know the order of intersection points.
|
260
|
-
const parts = path.splitAt(intersectionPoints, {
|
268
|
+
const parts = path.splitAt(intersectionPoints, {
|
269
|
+
mapNewPoint: (p) => viewport.roundPoint(p),
|
270
|
+
});
|
261
271
|
for (let i = 0; i < Math.floor(parts.length / 2); i++) {
|
262
272
|
addNewPath(parts[i].union(parts[parts.length - i - 1]).asClosed());
|
263
273
|
}
|
@@ -333,12 +343,12 @@ export default class Stroke extends AbstractComponent {
|
|
333
343
|
let occludes = false;
|
334
344
|
let skipSimplification = false;
|
335
345
|
for (const part of this.parts) {
|
336
|
-
if (skipSimplification
|
346
|
+
if (skipSimplification ||
|
337
347
|
// Simplification currently only works for stroked paths
|
338
|
-
|
348
|
+
!part.style.stroke ||
|
339
349
|
// One of the main purposes of this is to check for occlusion.
|
340
350
|
// We can't occlude things if the stroke is partially transparent.
|
341
|
-
|
351
|
+
part.style.stroke.color.a < 0.99) {
|
342
352
|
simplifiedParts.push(part);
|
343
353
|
continue;
|
344
354
|
}
|
@@ -388,7 +398,8 @@ export default class Stroke extends AbstractComponent {
|
|
388
398
|
continue;
|
389
399
|
}
|
390
400
|
const muchBiggerThanVisible = bbox.size.x > visibleRect.size.x * 3 || bbox.size.y > visibleRect.size.y * 3;
|
391
|
-
if (muchBiggerThanVisible &&
|
401
|
+
if (muchBiggerThanVisible &&
|
402
|
+
!part.path.roughlyIntersects(visibleRect, part.style.stroke?.width ?? 0)) {
|
392
403
|
continue;
|
393
404
|
}
|
394
405
|
}
|
@@ -424,9 +435,11 @@ export default class Stroke extends AbstractComponent {
|
|
424
435
|
const newPath = part.path.transformedBy(affineTransfm);
|
425
436
|
const newStyle = {
|
426
437
|
...part.style,
|
427
|
-
stroke: part.style.stroke
|
428
|
-
|
429
|
-
|
438
|
+
stroke: part.style.stroke
|
439
|
+
? {
|
440
|
+
...part.style.stroke,
|
441
|
+
}
|
442
|
+
: undefined,
|
430
443
|
};
|
431
444
|
// Approximate the scale factor.
|
432
445
|
if (newStyle.stroke) {
|
@@ -484,7 +497,7 @@ export default class Stroke extends AbstractComponent {
|
|
484
497
|
return new Stroke(this.parts);
|
485
498
|
}
|
486
499
|
serializeToJSON() {
|
487
|
-
return this.parts.map(part => {
|
500
|
+
return this.parts.map((part) => {
|
488
501
|
return {
|
489
502
|
style: styleToJSON(part.style),
|
490
503
|
path: part.path.serialize(),
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Vec2, Rect2, Mat33, Color4 } from '@js-draw/math';
|
2
|
-
import { cloneTextStyle, textStyleFromJSON, textStyleToJSON } from '../rendering/TextRenderingStyle.mjs';
|
2
|
+
import { cloneTextStyle, textStyleFromJSON, textStyleToJSON, } from '../rendering/TextRenderingStyle.mjs';
|
3
3
|
import AbstractComponent from './AbstractComponent.mjs';
|
4
|
-
import { createRestyleComponentCommand } from './RestylableComponent.mjs';
|
4
|
+
import { createRestyleComponentCommand, } from './RestylableComponent.mjs';
|
5
5
|
const componentTypeId = 'text';
|
6
6
|
export var TextTransformMode;
|
7
7
|
(function (TextTransformMode) {
|
@@ -15,7 +15,9 @@ export var TextTransformMode;
|
|
15
15
|
TextTransformMode[TextTransformMode["RELATIVE_Y_ABSOLUTE_X"] = 3] = "RELATIVE_Y_ABSOLUTE_X";
|
16
16
|
})(TextTransformMode || (TextTransformMode = {}));
|
17
17
|
const defaultTextStyle = {
|
18
|
-
fontFamily: 'sans',
|
18
|
+
fontFamily: 'sans',
|
19
|
+
size: 12,
|
20
|
+
renderingStyle: { fill: Color4.purple },
|
19
21
|
};
|
20
22
|
/**
|
21
23
|
* Displays text.
|
@@ -76,7 +78,7 @@ class TextComponent extends AbstractComponent {
|
|
76
78
|
this.recomputeBBox();
|
77
79
|
// If this has no direct children, choose a style representative of this' content
|
78
80
|
// (useful for estimating the style of the TextComponent).
|
79
|
-
const hasDirectContent = textObjects.some(obj => typeof obj === 'string');
|
81
|
+
const hasDirectContent = textObjects.some((obj) => typeof obj === 'string');
|
80
82
|
if (!hasDirectContent && textObjects.length > 0) {
|
81
83
|
this.style = textObjects[0].getTextStyle();
|
82
84
|
}
|
@@ -90,7 +92,7 @@ class TextComponent extends AbstractComponent {
|
|
90
92
|
style.fontStyle ?? '',
|
91
93
|
style.fontWeight ?? '',
|
92
94
|
(style.size ?? 12) + 'px',
|
93
|
-
`${fontFamily}
|
95
|
+
`${fontFamily}`,
|
94
96
|
].join(' ');
|
95
97
|
// TODO: Support RTL
|
96
98
|
ctx.textAlign = 'left';
|
@@ -101,7 +103,7 @@ class TextComponent extends AbstractComponent {
|
|
101
103
|
const heightEst = style.size;
|
102
104
|
// Text is drawn with (0, 0) as its baseline. As such, the majority of the text's height should
|
103
105
|
// be above (0, 0).
|
104
|
-
return new Rect2(0, -heightEst * 2 / 3, widthEst, heightEst);
|
106
|
+
return new Rect2(0, (-heightEst * 2) / 3, widthEst, heightEst);
|
105
107
|
}
|
106
108
|
// Returns a set of TextMetrics for the given text, if a canvas is available.
|
107
109
|
static getTextMetrics(text, style) {
|
@@ -181,7 +183,7 @@ class TextComponent extends AbstractComponent {
|
|
181
183
|
const textBBox = TextComponent.getTextDimens(subObject, this.style);
|
182
184
|
// TODO: Use a better intersection check. Perhaps draw the text onto a CanvasElement and
|
183
185
|
// use pixel-testing to check for intersection with its contour.
|
184
|
-
if (textBBox.getEdges().some(edge => transformedLine.intersection(edge) !== null)) {
|
186
|
+
if (textBBox.getEdges().some((edge) => transformedLine.intersection(edge) !== null)) {
|
185
187
|
return true;
|
186
188
|
}
|
187
189
|
}
|
@@ -249,7 +251,7 @@ class TextComponent extends AbstractComponent {
|
|
249
251
|
this.recomputeBBox();
|
250
252
|
}
|
251
253
|
createClone() {
|
252
|
-
const clonedTextObjects = this.textObjects.map(obj => {
|
254
|
+
const clonedTextObjects = this.textObjects.map((obj) => {
|
253
255
|
if (typeof obj === 'string') {
|
254
256
|
return obj;
|
255
257
|
}
|
@@ -277,7 +279,7 @@ class TextComponent extends AbstractComponent {
|
|
277
279
|
// Do not rely on the output of `serializeToJSON` taking any particular format.
|
278
280
|
serializeToJSON() {
|
279
281
|
const serializableStyle = textStyleToJSON(this.style);
|
280
|
-
const serializedTextObjects = this.textObjects.map(text => {
|
282
|
+
const serializedTextObjects = this.textObjects.map((text) => {
|
281
283
|
if (typeof text === 'string') {
|
282
284
|
return {
|
283
285
|
text,
|
@@ -363,7 +365,7 @@ TextComponent.TextCursor = class {
|
|
363
365
|
let elementTransform = Mat33.identity;
|
364
366
|
let elemInternalTransform = Mat33.identity;
|
365
367
|
let textSize;
|
366
|
-
if (typeof
|
368
|
+
if (typeof elem === 'string') {
|
367
369
|
textSize = TextComponent.getTextDimens(elem, this.parentStyle);
|
368
370
|
}
|
369
371
|
else {
|
@@ -372,12 +374,13 @@ TextComponent.TextCursor = class {
|
|
372
374
|
elemInternalTransform = elem.transform;
|
373
375
|
textSize = elem.getBBox();
|
374
376
|
}
|
375
|
-
const positioning = typeof
|
377
|
+
const positioning = typeof elem === 'string' ? TextTransformMode.RELATIVE_XY : elem.transformMode;
|
376
378
|
if (positioning === TextTransformMode.RELATIVE_XY) {
|
377
379
|
// Position relative to the previous element's transform.
|
378
380
|
elementTransform = this.transform.rightMul(elementTransform);
|
379
381
|
}
|
380
|
-
else if (positioning === TextTransformMode.RELATIVE_X_ABSOLUTE_Y ||
|
382
|
+
else if (positioning === TextTransformMode.RELATIVE_X_ABSOLUTE_Y ||
|
383
|
+
positioning === TextTransformMode.RELATIVE_Y_ABSOLUTE_X) {
|
381
384
|
// Zero the absolute component of this.transform's translation
|
382
385
|
const transform = this.transform.mapEntries((component, [row, col]) => {
|
383
386
|
if (positioning === TextTransformMode.RELATIVE_X_ABSOLUTE_Y) {
|
@@ -23,10 +23,9 @@ export default class UnknownSVGObject extends AbstractComponent {
|
|
23
23
|
canvas.endObject(this.getLoadSaveData());
|
24
24
|
}
|
25
25
|
intersects(lineSegment) {
|
26
|
-
return this.contentBBox.getEdges().some(edge => edge.intersection(lineSegment) !== null);
|
27
|
-
}
|
28
|
-
applyTransformation(_affineTransfm) {
|
26
|
+
return this.contentBBox.getEdges().some((edge) => edge.intersection(lineSegment) !== null);
|
29
27
|
}
|
28
|
+
applyTransformation(_affineTransfm) { }
|
30
29
|
isSelectable() {
|
31
30
|
return false;
|
32
31
|
}
|
@@ -4,6 +4,12 @@ import { StrokeDataPoint } from '../../types';
|
|
4
4
|
import Viewport from '../../Viewport';
|
5
5
|
import AbstractComponent from '../AbstractComponent';
|
6
6
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
7
|
+
/**
|
8
|
+
* Creates a stroke builder that generates arrows circles.
|
9
|
+
*
|
10
|
+
* Example:
|
11
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
|
+
*/
|
7
13
|
export declare const makeArrowBuilder: ComponentBuilderFactory;
|
8
14
|
export default class ArrowBuilder implements ComponentBuilder {
|
9
15
|
private readonly startPoint;
|
@@ -1,6 +1,12 @@
|
|
1
1
|
import { Path, PathCommandType } from '@js-draw/math';
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
3
|
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
4
|
+
/**
|
5
|
+
* Creates a stroke builder that generates arrows circles.
|
6
|
+
*
|
7
|
+
* Example:
|
8
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
9
|
+
*/
|
4
10
|
export const makeArrowBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
5
11
|
return new ArrowBuilder(initialPoint, viewport);
|
6
12
|
});
|
@@ -63,15 +69,15 @@ export default class ArrowBuilder {
|
|
63
69
|
point: arrowTipBase.minus(scaledBaseNormal),
|
64
70
|
},
|
65
71
|
// Round all points in the arrow (to remove unnecessary decimal places)
|
66
|
-
]).mapPoints(point => this.viewport.roundPoint(point));
|
72
|
+
]).mapPoints((point) => this.viewport.roundPoint(point));
|
67
73
|
const preview = new Stroke([
|
68
74
|
{
|
69
75
|
startPoint: path.startPoint,
|
70
76
|
commands: path.parts,
|
71
77
|
style: {
|
72
78
|
fill: this.startPoint.color,
|
73
|
-
}
|
74
|
-
}
|
79
|
+
},
|
80
|
+
},
|
75
81
|
]);
|
76
82
|
return preview;
|
77
83
|
}
|
@@ -1,2 +1,8 @@
|
|
1
1
|
import { ComponentBuilderFactory } from './types';
|
2
|
+
/**
|
3
|
+
* Creates a stroke builder that generates outlined circles.
|
4
|
+
*
|
5
|
+
* Example:
|
6
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
7
|
+
*/
|
2
8
|
export declare const makeOutlinedCircleBuilder: ComponentBuilderFactory;
|
@@ -3,6 +3,12 @@ import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import Stroke from '../Stroke.mjs';
|
5
5
|
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
6
|
+
/**
|
7
|
+
* Creates a stroke builder that generates outlined circles.
|
8
|
+
*
|
9
|
+
* Example:
|
10
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
11
|
+
*/
|
6
12
|
export const makeOutlinedCircleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
7
13
|
return new CircleBuilder(initialPoint, viewport);
|
8
14
|
});
|
@@ -20,7 +26,7 @@ class CircleBuilder {
|
|
20
26
|
buildPreview() {
|
21
27
|
const pathCommands = [];
|
22
28
|
const numDivisions = 6;
|
23
|
-
const stepSize = Math.PI * 2 / numDivisions;
|
29
|
+
const stepSize = (Math.PI * 2) / numDivisions;
|
24
30
|
// Round the stroke width so that when exported it doesn't have unnecessary trailing decimals.
|
25
31
|
const strokeWidth = Viewport.roundPoint(this.endPoint.width, 5 / this.viewport.getScaleFactor());
|
26
32
|
const center = this.startPoint.pos.lerp(this.endPoint.pos, 0.5);
|
@@ -32,7 +38,9 @@ class CircleBuilder {
|
|
32
38
|
// controlPointRadiusScale is selected to make the circles appear circular and
|
33
39
|
// **does** depend on stepSize.
|
34
40
|
const controlPointRadiusScale = 1.141;
|
35
|
-
const controlPoint = Vec2.of(Math.cos(t - stepSize / 2), -Math.sin(t - stepSize / 2))
|
41
|
+
const controlPoint = Vec2.of(Math.cos(t - stepSize / 2), -Math.sin(t - stepSize / 2))
|
42
|
+
.times(radius * controlPointRadiusScale)
|
43
|
+
.plus(center);
|
36
44
|
pathCommands.push({
|
37
45
|
kind: PathCommandType.QuadraticBezierTo,
|
38
46
|
controlPoint,
|
@@ -43,8 +51,7 @@ class CircleBuilder {
|
|
43
51
|
kind: PathCommandType.LineTo,
|
44
52
|
point: startPoint,
|
45
53
|
});
|
46
|
-
const path = new Path(startPoint, pathCommands)
|
47
|
-
.mapPoints(point => this.viewport.roundPoint(point));
|
54
|
+
const path = new Path(startPoint, pathCommands).mapPoints((point) => this.viewport.roundPoint(point));
|
48
55
|
const preview = new Stroke([
|
49
56
|
pathToRenderable(path, {
|
50
57
|
fill: Color4.transparent,
|
@@ -6,6 +6,12 @@ import Viewport from '../../Viewport';
|
|
6
6
|
import { StrokeDataPoint } from '../../types';
|
7
7
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
8
8
|
import RenderingStyle from '../../rendering/RenderingStyle';
|
9
|
+
/**
|
10
|
+
* Creates a stroke builder that draws freehand lines.
|
11
|
+
*
|
12
|
+
* Example:
|
13
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
14
|
+
*/
|
9
15
|
export declare const makeFreehandLineBuilder: ComponentBuilderFactory;
|
10
16
|
export default class FreehandLineBuilder implements ComponentBuilder {
|
11
17
|
private startPoint;
|
@@ -3,6 +3,12 @@ import Stroke from '../Stroke.mjs';
|
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import { StrokeSmoother } from '../util/StrokeSmoother.mjs';
|
5
5
|
import makeShapeFitAutocorrect from './autocorrect/makeShapeFitAutocorrect.mjs';
|
6
|
+
/**
|
7
|
+
* Creates a stroke builder that draws freehand lines.
|
8
|
+
*
|
9
|
+
* Example:
|
10
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
11
|
+
*/
|
6
12
|
export const makeFreehandLineBuilder = makeShapeFitAutocorrect((initialPoint, viewport) => {
|
7
13
|
// Don't smooth if input is more than ± 3 pixels from the true curve, do smooth if
|
8
14
|
// less than ±1 px from the curve.
|
@@ -32,7 +38,7 @@ export default class FreehandLineBuilder {
|
|
32
38
|
stroke: {
|
33
39
|
color: this.startPoint.color,
|
34
40
|
width: this.roundDistance(this.averageWidth),
|
35
|
-
}
|
41
|
+
},
|
36
42
|
};
|
37
43
|
}
|
38
44
|
previewCurrentPath() {
|
@@ -129,7 +135,7 @@ export default class FreehandLineBuilder {
|
|
129
135
|
kind: PathCommandType.QuadraticBezierTo,
|
130
136
|
controlPoint: center.plus(Vec2.of(width, -width)),
|
131
137
|
endPoint: center.plus(Vec2.of(width, 0)),
|
132
|
-
}
|
138
|
+
},
|
133
139
|
];
|
134
140
|
}
|
135
141
|
const result = [];
|
@@ -157,7 +163,7 @@ export default class FreehandLineBuilder {
|
|
157
163
|
this.curveFitter.addPoint(newPoint);
|
158
164
|
this.widthAverageNumSamples++;
|
159
165
|
this.averageWidth =
|
160
|
-
this.averageWidth * (this.widthAverageNumSamples - 1) / this.widthAverageNumSamples
|
161
|
-
|
166
|
+
(this.averageWidth * (this.widthAverageNumSamples - 1)) / this.widthAverageNumSamples +
|
167
|
+
newPoint.width / this.widthAverageNumSamples;
|
162
168
|
}
|
163
169
|
}
|
@@ -4,6 +4,12 @@ import { StrokeDataPoint } from '../../types';
|
|
4
4
|
import Viewport from '../../Viewport';
|
5
5
|
import AbstractComponent from '../AbstractComponent';
|
6
6
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
7
|
+
/**
|
8
|
+
* Creates a stroke builder that generates filled lines.
|
9
|
+
*
|
10
|
+
* Example:
|
11
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
|
+
*/
|
7
13
|
export declare const makeLineBuilder: ComponentBuilderFactory;
|
8
14
|
export default class LineBuilder implements ComponentBuilder {
|
9
15
|
private readonly startPoint;
|
@@ -2,6 +2,12 @@ import { Path, PathCommandType } 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 a stroke builder that generates filled lines.
|
7
|
+
*
|
8
|
+
* Example:
|
9
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
10
|
+
*/
|
5
11
|
export const makeLineBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
6
12
|
return new LineBuilder(initialPoint, viewport);
|
7
13
|
});
|
@@ -42,10 +48,8 @@ export default class LineBuilder {
|
|
42
48
|
kind: PathCommandType.LineTo,
|
43
49
|
point: startPoint.minus(scaledStartNormal),
|
44
50
|
},
|
45
|
-
]).mapPoints(point => this.viewport.roundPoint(point));
|
46
|
-
const preview = new Stroke([
|
47
|
-
pathToRenderable(path, { fill: this.startPoint.color })
|
48
|
-
]);
|
51
|
+
]).mapPoints((point) => this.viewport.roundPoint(point));
|
52
|
+
const preview = new Stroke([pathToRenderable(path, { fill: this.startPoint.color })]);
|
49
53
|
return preview;
|
50
54
|
}
|
51
55
|
build() {
|
@@ -7,8 +7,11 @@ import { StrokeDataPoint } from '../../types';
|
|
7
7
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
8
8
|
import RenderingStyle from '../../rendering/RenderingStyle';
|
9
9
|
/**
|
10
|
-
* Creates
|
10
|
+
* Creates a freehand line builder that creates strokes from line segments
|
11
|
+
* rather than Bézier curves.
|
11
12
|
*
|
13
|
+
* Example:
|
14
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
15
|
*/
|
13
16
|
export declare const makePolylineBuilder: ComponentBuilderFactory;
|
14
17
|
export default class PolylineBuilder implements ComponentBuilder {
|
@@ -1,10 +1,13 @@
|
|
1
|
-
import { Rect2, Color4, PathCommandType, Vec2, LineSegment2 } from '@js-draw/math';
|
1
|
+
import { Rect2, Color4, PathCommandType, Vec2, LineSegment2, } from '@js-draw/math';
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import makeShapeFitAutocorrect from './autocorrect/makeShapeFitAutocorrect.mjs';
|
5
5
|
/**
|
6
|
-
* Creates
|
6
|
+
* Creates a freehand line builder that creates strokes from line segments
|
7
|
+
* rather than Bézier curves.
|
7
8
|
*
|
9
|
+
* Example:
|
10
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
8
11
|
*/
|
9
12
|
export const makePolylineBuilder = makeShapeFitAutocorrect((initialPoint, viewport) => {
|
10
13
|
// Fit to a value slightly smaller than the pixel size. A larger value can
|
@@ -42,7 +45,7 @@ export default class PolylineBuilder {
|
|
42
45
|
stroke: {
|
43
46
|
color: this.startPoint.color,
|
44
47
|
width: this.roundDistance(this.averageWidth),
|
45
|
-
}
|
48
|
+
},
|
46
49
|
};
|
47
50
|
}
|
48
51
|
previewCurrentPath() {
|
@@ -96,12 +99,13 @@ export default class PolylineBuilder {
|
|
96
99
|
addPoint(newPoint) {
|
97
100
|
this.widthAverageNumSamples++;
|
98
101
|
this.averageWidth =
|
99
|
-
this.averageWidth * (this.widthAverageNumSamples - 1) / this.widthAverageNumSamples
|
100
|
-
|
102
|
+
(this.averageWidth * (this.widthAverageNumSamples - 1)) / this.widthAverageNumSamples +
|
103
|
+
newPoint.width / this.widthAverageNumSamples;
|
101
104
|
const roundedPoint = this.roundPoint(newPoint.pos);
|
102
105
|
if (!roundedPoint.eq(this.lastPoint)) {
|
103
106
|
// If almost exactly in the same line as the previous
|
104
|
-
if (this.lastLineSegment &&
|
107
|
+
if (this.lastLineSegment &&
|
108
|
+
this.lastLineSegment.direction.dot(roundedPoint.minus(this.lastPoint).normalized()) > 0.997) {
|
105
109
|
this.parts.pop();
|
106
110
|
this.lastPoint = this.lastLineSegment.p1;
|
107
111
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Vec2, Rect2, PathCommandType, QuadraticBezier } from '@js-draw/math';
|
1
|
+
import { Vec2, Rect2, PathCommandType, QuadraticBezier, } from '@js-draw/math';
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import { StrokeSmoother } from '../util/StrokeSmoother.mjs';
|
@@ -30,7 +30,7 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
30
30
|
this.parts = [];
|
31
31
|
this.upperSegments = [];
|
32
32
|
this.lowerSegments = [];
|
33
|
-
this.curveFitter = new StrokeSmoother(startPoint, minFitAllowed, maxFitAllowed, curve => this.addCurve(curve));
|
33
|
+
this.curveFitter = new StrokeSmoother(startPoint, minFitAllowed, maxFitAllowed, (curve) => this.addCurve(curve));
|
34
34
|
this.curveStartWidth = startPoint.width;
|
35
35
|
this.bbox = new Rect2(this.startPoint.pos.x, this.startPoint.pos.y, 0, 0);
|
36
36
|
}
|
@@ -64,7 +64,8 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
64
64
|
}
|
65
65
|
let startPoint;
|
66
66
|
const lastLowerSegment = lowerPath[lowerPath.length - 1];
|
67
|
-
if (lastLowerSegment.kind === PathCommandType.LineTo ||
|
67
|
+
if (lastLowerSegment.kind === PathCommandType.LineTo ||
|
68
|
+
lastLowerSegment.kind === PathCommandType.MoveTo) {
|
68
69
|
startPoint = lastLowerSegment.point;
|
69
70
|
}
|
70
71
|
else {
|
@@ -163,11 +164,11 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
163
164
|
// where the next stroke and the previous stroke are in different directions.
|
164
165
|
//
|
165
166
|
// Are the exit/enter directions of the previous and current curves in different enough directions?
|
166
|
-
if (getEnterDirection(upperCurve).dot(getExitDirection(this.lastUpperBezier)) < 0.35
|
167
|
-
|
167
|
+
if (getEnterDirection(upperCurve).dot(getExitDirection(this.lastUpperBezier)) < 0.35 ||
|
168
|
+
getEnterDirection(lowerCurve).dot(getExitDirection(this.lastLowerBezier)) < 0.35 ||
|
168
169
|
// Also handle if the curves exit/enter directions differ
|
169
|
-
|
170
|
-
|
170
|
+
getEnterDirection(upperCurve).dot(getExitDirection(upperCurve)) < 0 ||
|
171
|
+
getEnterDirection(lowerCurve).dot(getExitDirection(lowerCurve)) < 0) {
|
171
172
|
return true;
|
172
173
|
}
|
173
174
|
// Check whether the lower curve intersects the other wall:
|
@@ -274,8 +275,9 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
274
275
|
// Approximate the normal at the location of the control point
|
275
276
|
const projectionT = bezier.nearestPointTo(controlPoint).parameterValue;
|
276
277
|
const halfVecT = projectionT;
|
277
|
-
const halfVec = bezier
|
278
|
-
|
278
|
+
const halfVec = bezier
|
279
|
+
.normal(halfVecT)
|
280
|
+
.times((curve.startWidth / 2) * halfVecT + (curve.endWidth / 2) * (1 - halfVecT));
|
279
281
|
// Each starts at startPt ± startVec
|
280
282
|
const lowerCurveStartPoint = this.roundPoint(startPt.plus(startVec));
|
281
283
|
const lowerCurveControlPoint = this.roundPoint(controlPoint.plus(halfVec));
|
@@ -318,8 +320,12 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
318
320
|
const upperCurve = new QuadraticBezier(upperCurveStartPoint, upperCurveControlPoint, upperCurveEndPoint);
|
319
321
|
const lowerCurve = new QuadraticBezier(lowerCurveStartPoint, lowerCurveControlPoint, lowerCurveEndPoint);
|
320
322
|
return {
|
321
|
-
upperCurveCommand,
|
322
|
-
|
323
|
+
upperCurveCommand,
|
324
|
+
upperToLowerConnector,
|
325
|
+
lowerToUpperConnector,
|
326
|
+
lowerCurveCommand,
|
327
|
+
upperCurve,
|
328
|
+
lowerCurve,
|
323
329
|
nextCurveStartConnector,
|
324
330
|
};
|
325
331
|
}
|
@@ -4,7 +4,19 @@ import { StrokeDataPoint } from '../../types';
|
|
4
4
|
import Viewport from '../../Viewport';
|
5
5
|
import AbstractComponent from '../AbstractComponent';
|
6
6
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
7
|
+
/**
|
8
|
+
* Creates filled rectangles with sharp corners.
|
9
|
+
*
|
10
|
+
* Example:
|
11
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
|
+
*/
|
7
13
|
export declare const makeFilledRectangleBuilder: ComponentBuilderFactory;
|
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 declare const makeOutlinedRectangleBuilder: ComponentBuilderFactory;
|
9
21
|
export default class RectangleBuilder implements ComponentBuilder {
|
10
22
|
private readonly startPoint;
|