From c1143c2233d48bf4c101ffe799fe4fbfb18ac24e Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Thu, 3 Oct 2024 16:17:46 +0200 Subject: [PATCH 01/19] started to implement magic contour selection with pointer tool --- src/fontra/views/editor/edit-tools-pointer.js | 143 ++++++++++-------- 1 file changed, 83 insertions(+), 60 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 4bab67aa2..586208a87 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -113,6 +113,23 @@ export class PointerTool extends BaseTool { } } + selectContour(sceneController, contourIndex, selectModeFunction) { + const instance = this.sceneModel.getSelectedPositionedGlyph().glyph.instance; + const startPoint = instance.path.getAbsolutePointIndex(contourIndex, 0); + const endPoint = instance.path.contourInfo[contourIndex].endPoint; + const newSelection = new Set(); + for (const i of range(startPoint, endPoint + 1)) { + const pointType = instance.path.pointTypes[i] & VarPackedPath.POINT_TYPE_MASK; + if (pointType === VarPackedPath.ON_CURVE) { + newSelection.add(`point/${i}`); + } + } + const sselection = this._selectionBeforeSingleClick || sceneController.selection; + this._selectionBeforeSingleClick = undefined; + const modeFunc = selectModeFunction(event); + sceneController.selection = modeFunc(sselection, newSelection); + } + async handleDrag(eventStream, initialEvent) { const sceneController = this.sceneController; const initialSelection = sceneController.selection; @@ -159,57 +176,65 @@ export class PointerTool extends BaseTool { eventStream.done(); return; } - - let initiateDrag = false; - let initiateRectSelect = false; - - const modeFunc = getSelectModeFunction(event); - const newSelection = modeFunc(sceneController.selection, selection); - const cleanSel = selection; - if ( - !selection.size || - event.shiftKey || - event.altKey || - !isSuperset(sceneController.selection, cleanSel) - ) { - this._selectionBeforeSingleClick = sceneController.selection; - sceneController.selection = newSelection; - } - - if (isSuperset(sceneController.selection, cleanSel)) { - initiateDrag = true; - } - if (!selection.size) { - initiateRectSelect = true; - } - - if (initiateRectSelect || initiateDrag) { - if (!(await shouldInitiateDrag(eventStream, initialEvent))) { - initiateRectSelect = false; - initiateDrag = false; - if (!selection.size) { - const selectedGlyph = this.sceneModel.glyphAtPoint(point); - if ( - selectedGlyph && - !equalGlyphSelection(selectedGlyph, this.sceneSettings.selectedGlyph) - ) { - this.sceneSettings.selectedGlyph = selectedGlyph; - eventStream.done(); - return; + if (initialEvent.metaKey) { + const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); + const positionedGlyph = this.sceneModel.getSelectedPositionedGlyph(); + point.x -= positionedGlyph.x; + point.y -= positionedGlyph.y; + const pathHitTester = glyphController.flattenedPathHitTester; + const nearestHit = pathHitTester.findNearest(point); + const contourIndex = nearestHit.contourIndex; + this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + } else { + let initiateDrag = false; + let initiateRectSelect = false; + + const modeFunc = getSelectModeFunction(event); + const newSelection = modeFunc(sceneController.selection, selection); + const cleanSel = selection; + if ( + !selection.size || + event.shiftKey || + event.altKey || + !isSuperset(sceneController.selection, cleanSel) + ) { + this._selectionBeforeSingleClick = sceneController.selection; + sceneController.selection = newSelection; + } + if (isSuperset(sceneController.selection, cleanSel)) { + initiateDrag = true; + } + if (!selection.size) { + initiateRectSelect = true; + } + if (initiateRectSelect || initiateDrag) { + if (!(await shouldInitiateDrag(eventStream, initialEvent))) { + initiateRectSelect = false; + initiateDrag = false; + if (!selection.size) { + const selectedGlyph = this.sceneModel.glyphAtPoint(point); + if ( + selectedGlyph && + !equalGlyphSelection(selectedGlyph, this.sceneSettings.selectedGlyph) + ) { + this.sceneSettings.selectedGlyph = selectedGlyph; + eventStream.done(); + return; + } } } } - } - sceneController.hoveredGlyph = undefined; - if (initiateRectSelect) { - return await this.handleRectSelect(eventStream, initialEvent, initialSelection); - } else if (initiateDrag) { - this.sceneController.sceneModel.initialClickedPointIndex = - initialClickedPointIndex; - const result = await this.handleDragSelection(eventStream, initialEvent); - delete this.sceneController.sceneModel.initialClickedPointIndex; - return result; + sceneController.hoveredGlyph = undefined; + if (initiateRectSelect) { + return await this.handleRectSelect(eventStream, initialEvent, initialSelection); + } else if (initiateDrag) { + this.sceneController.sceneModel.initialClickedPointIndex = + initialClickedPointIndex; + const result = await this.handleDragSelection(eventStream, initialEvent); + delete this.sceneController.sceneModel.initialClickedPointIndex; + return result; + } } } @@ -259,19 +284,7 @@ export class PointerTool extends BaseTool { await this.handlePointsDoubleClick(pointIndices); } else if (sceneController.hoverPathHit) { const contourIndex = sceneController.hoverPathHit.contourIndex; - const startPoint = instance.path.getAbsolutePointIndex(contourIndex, 0); - const endPoint = instance.path.contourInfo[contourIndex].endPoint; - const newSelection = new Set(); - for (const i of range(startPoint, endPoint + 1)) { - const pointType = instance.path.pointTypes[i] & VarPackedPath.POINT_TYPE_MASK; - if (pointType === VarPackedPath.ON_CURVE) { - newSelection.add(`point/${i}`); - } - } - const selection = this._selectionBeforeSingleClick || sceneController.selection; - this._selectionBeforeSingleClick = undefined; - const modeFunc = getSelectModeFunction(event); - sceneController.selection = modeFunc(selection, newSelection); + this.selectContour(sceneController, contourIndex, getSelectModeFunction); } } } @@ -695,6 +708,16 @@ function getSelectModeFunction(event) { : replace; } +function getMagicSelectModeFunction(event) { + return event.shiftKey + ? event[commandKeyProperty] + ? union + : symmetricDifference + : event[commandKeyProperty] + ? replace + : union; +} + registerVisualizationLayerDefinition({ identifier: "fontra.transform.selection", name: "Transform selection", From 99927e76456417c5af269fc8aa11ee9c57c970dc Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Tue, 8 Oct 2024 16:43:25 +0200 Subject: [PATCH 02/19] magic selection handled with mouse drag --- src/fontra/views/editor/edit-tools-pointer.js | 108 +++++++++++------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 586208a87..2ab4d409a 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -130,6 +130,16 @@ export class PointerTool extends BaseTool { sceneController.selection = modeFunc(sselection, newSelection); } + getNearestHit(sceneController, event, glyphController) { + const positionedGlyph = this.sceneModel.getSelectedPositionedGlyph(); + const point = sceneController.localPoint(event); + point.x -= positionedGlyph.x; + point.y -= positionedGlyph.y; + const pathHitTester = glyphController.flattenedPathHitTester; + const nearestHit = pathHitTester.findNearest(point); + return nearestHit; + } + async handleDrag(eventStream, initialEvent) { const sceneController = this.sceneController; const initialSelection = sceneController.selection; @@ -176,54 +186,57 @@ export class PointerTool extends BaseTool { eventStream.done(); return; } + let initiateDrag = false; + let initiateRectSelect = false; + + const modeFunc = getSelectModeFunction(event); + const newSelection = modeFunc(sceneController.selection, selection); + const cleanSel = selection; + + if ( + !selection.size || + event.shiftKey || + event.altKey || + !isSuperset(sceneController.selection, cleanSel) + ) { + this._selectionBeforeSingleClick = sceneController.selection; + sceneController.selection = newSelection; + } + if (isSuperset(sceneController.selection, cleanSel)) { + initiateDrag = true; + } + if (!selection.size) { + initiateRectSelect = true; + } + + if (initiateRectSelect || initiateDrag) { + if (!(await shouldInitiateDrag(eventStream, initialEvent))) { + initiateRectSelect = false; + initiateDrag = false; + if (!selection.size) { + const selectedGlyph = this.sceneModel.glyphAtPoint(point); + if ( + selectedGlyph && + !equalGlyphSelection(selectedGlyph, this.sceneSettings.selectedGlyph) + ) { + this.sceneSettings.selectedGlyph = selectedGlyph; + eventStream.done(); + return; + } + } + } + } + if (initialEvent.metaKey) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); - const positionedGlyph = this.sceneModel.getSelectedPositionedGlyph(); - point.x -= positionedGlyph.x; - point.y -= positionedGlyph.y; - const pathHitTester = glyphController.flattenedPathHitTester; - const nearestHit = pathHitTester.findNearest(point); + const nearestHit = this.getNearestHit(sceneController, initialEvent, glyphController); const contourIndex = nearestHit.contourIndex; this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); - } else { - let initiateDrag = false; - let initiateRectSelect = false; - - const modeFunc = getSelectModeFunction(event); - const newSelection = modeFunc(sceneController.selection, selection); - const cleanSel = selection; - if ( - !selection.size || - event.shiftKey || - event.altKey || - !isSuperset(sceneController.selection, cleanSel) - ) { - this._selectionBeforeSingleClick = sceneController.selection; - sceneController.selection = newSelection; - } - if (isSuperset(sceneController.selection, cleanSel)) { - initiateDrag = true; - } - if (!selection.size) { - initiateRectSelect = true; - } - if (initiateRectSelect || initiateDrag) { - if (!(await shouldInitiateDrag(eventStream, initialEvent))) { - initiateRectSelect = false; - initiateDrag = false; - if (!selection.size) { - const selectedGlyph = this.sceneModel.glyphAtPoint(point); - if ( - selectedGlyph && - !equalGlyphSelection(selectedGlyph, this.sceneSettings.selectedGlyph) - ) { - this.sceneSettings.selectedGlyph = selectedGlyph; - eventStream.done(); - return; - } - } - } + + if (initiateRectSelect){ + return await this.handleMagicSelect(eventStream, sceneController); } + } else { sceneController.hoveredGlyph = undefined; if (initiateRectSelect) { @@ -332,6 +345,15 @@ export class PointerTool extends BaseTool { this._selectionBeforeSingleClick = undefined; } + async handleMagicSelect(eventStream, sceneController) { + const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); + for await (const event of eventStream) { + const nearestHit = this.getNearestHit(sceneController, event, glyphController); + const contourIndex = nearestHit.contourIndex; + this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + } + } + async handleDragSelection(eventStream, initialEvent) { this.sceneController.sceneModel.showTransformSelection = false; this._selectionBeforeSingleClick = undefined; From 66bc55383252df7de10642439fc911a611fe3b32 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Tue, 8 Oct 2024 17:01:56 +0200 Subject: [PATCH 03/19] typo --- src/fontra/views/editor/edit-tools-pointer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 2ab4d409a..0d370e719 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -124,10 +124,10 @@ export class PointerTool extends BaseTool { newSelection.add(`point/${i}`); } } - const sselection = this._selectionBeforeSingleClick || sceneController.selection; + const selection = this._selectionBeforeSingleClick || sceneController.selection; this._selectionBeforeSingleClick = undefined; const modeFunc = selectModeFunction(event); - sceneController.selection = modeFunc(sselection, newSelection); + sceneController.selection = modeFunc(selection, newSelection); } getNearestHit(sceneController, event, glyphController) { From b13523b90bb67f9e74536dbdba42c37ec5592b32 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Tue, 8 Oct 2024 18:00:21 +0200 Subject: [PATCH 04/19] magic selection: draw line from cursor to nearest point --- src/fontra/views/editor/edit-tools-pointer.js | 3 +++ .../editor/visualization-layer-definitions.js | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 0d370e719..603b451d2 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -58,6 +58,7 @@ export class PointerTool extends BaseTool { sceneController.hoverSelection = selection; sceneController.hoveredGlyph = undefined; sceneController.hoverPathHit = pathHit; + sceneController.sceneModel.magicSelection = []; if (!sceneController.hoverSelection.size && !sceneController.hoverPathHit) { sceneController.hoveredGlyph = this.sceneModel.glyphAtPoint(point); @@ -125,6 +126,7 @@ export class PointerTool extends BaseTool { } } const selection = this._selectionBeforeSingleClick || sceneController.selection; + sceneController.selection = undefined; this._selectionBeforeSingleClick = undefined; const modeFunc = selectModeFunction(event); sceneController.selection = modeFunc(selection, newSelection); @@ -137,6 +139,7 @@ export class PointerTool extends BaseTool { point.y -= positionedGlyph.y; const pathHitTester = glyphController.flattenedPathHitTester; const nearestHit = pathHitTester.findNearest(point); + sceneController.sceneModel.magicSelection = [point.x, point.y, nearestHit.x, nearestHit.y]; return nearestHit; } diff --git a/src/fontra/views/editor/visualization-layer-definitions.js b/src/fontra/views/editor/visualization-layer-definitions.js index 89937ff3e..c9f888435 100644 --- a/src/fontra/views/editor/visualization-layer-definitions.js +++ b/src/fontra/views/editor/visualization-layer-definitions.js @@ -1545,6 +1545,29 @@ registerVisualizationLayerDefinition({ }, }); +registerVisualizationLayerDefinition({ + identifier: "fontra.magic.select", + name: "Magic select", + selectionMode: "editing", + zIndex: 500, + screenParameters: { + strokeWidth: 1, + lineDash: [10, 10], + }, + draw: (context, positionedGlyph, parameters, model, controller) => { + if (model.magicSelection === undefined) { + return; + } + const selRect = model.magicSelection; + const x = selRect[0]; + const y = selRect[1]; + const w = selRect[2]; + const h = selRect[3]; + context.lineWidth = parameters.strokeWidth; + strokeLineDashed(context, x, y, w, h); + }, +}); + registerVisualizationLayerDefinition({ identifier: "fontra.rect.select", name: "Rect select", From 5ae700858eebca4f3c8438cd0c9457db3db9b8b5 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Tue, 8 Oct 2024 18:01:41 +0200 Subject: [PATCH 05/19] renamed variables --- .../views/editor/visualization-layer-definitions.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fontra/views/editor/visualization-layer-definitions.js b/src/fontra/views/editor/visualization-layer-definitions.js index c9f888435..48dc61096 100644 --- a/src/fontra/views/editor/visualization-layer-definitions.js +++ b/src/fontra/views/editor/visualization-layer-definitions.js @@ -1559,12 +1559,12 @@ registerVisualizationLayerDefinition({ return; } const selRect = model.magicSelection; - const x = selRect[0]; - const y = selRect[1]; - const w = selRect[2]; - const h = selRect[3]; + const p1x = selRect[0]; + const p1y = selRect[1]; + const p2x = selRect[2]; + const p2y = selRect[3]; context.lineWidth = parameters.strokeWidth; - strokeLineDashed(context, x, y, w, h); + strokeLineDashed(context, p1x, p1y, p2x, p2y); }, }); From 76ddff7af334dfbdf2125dd4b92e7014aa7361d2 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 09:30:59 +0200 Subject: [PATCH 06/19] added a getter and setter for magic selection in scene controller --- src/fontra/views/editor/edit-tools-pointer.js | 5 ++--- src/fontra/views/editor/scene-controller.js | 9 +++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 603b451d2..cbeb26f3a 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -58,7 +58,7 @@ export class PointerTool extends BaseTool { sceneController.hoverSelection = selection; sceneController.hoveredGlyph = undefined; sceneController.hoverPathHit = pathHit; - sceneController.sceneModel.magicSelection = []; + sceneController.magicSelection = []; if (!sceneController.hoverSelection.size && !sceneController.hoverPathHit) { sceneController.hoveredGlyph = this.sceneModel.glyphAtPoint(point); @@ -126,7 +126,6 @@ export class PointerTool extends BaseTool { } } const selection = this._selectionBeforeSingleClick || sceneController.selection; - sceneController.selection = undefined; this._selectionBeforeSingleClick = undefined; const modeFunc = selectModeFunction(event); sceneController.selection = modeFunc(selection, newSelection); @@ -139,7 +138,7 @@ export class PointerTool extends BaseTool { point.y -= positionedGlyph.y; const pathHitTester = glyphController.flattenedPathHitTester; const nearestHit = pathHitTester.findNearest(point); - sceneController.sceneModel.magicSelection = [point.x, point.y, nearestHit.x, nearestHit.y]; + sceneController.magicSelection = [point.x, point.y, nearestHit.x, nearestHit.y]; return nearestHit; } diff --git a/src/fontra/views/editor/scene-controller.js b/src/fontra/views/editor/scene-controller.js index fb9855a0b..9f4ffdec3 100644 --- a/src/fontra/views/editor/scene-controller.js +++ b/src/fontra/views/editor/scene-controller.js @@ -831,6 +831,15 @@ export class SceneController { this.canvasController.requestUpdate(); } + get magicSelection() { + return this.sceneModel.magicSelection; + } + + set magicSelection(magicSel) { + this.sceneModel.magicSelection = magicSel; + this.canvasController.requestUpdate(); + } + get backgroundLayers() { return this.sceneModel.backgroundLayers || []; } From 245f16d46ff2f761050500f1bdb2a6a6f8849a77 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 09:48:29 +0200 Subject: [PATCH 07/19] renamed magicSelection for magicSelectionHit --- src/fontra/views/editor/edit-tools-pointer.js | 4 ++-- src/fontra/views/editor/scene-controller.js | 8 ++++---- .../views/editor/visualization-layer-definitions.js | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index cbeb26f3a..fcbe2ff82 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -58,7 +58,7 @@ export class PointerTool extends BaseTool { sceneController.hoverSelection = selection; sceneController.hoveredGlyph = undefined; sceneController.hoverPathHit = pathHit; - sceneController.magicSelection = []; + sceneController.magicSelectionHit = []; if (!sceneController.hoverSelection.size && !sceneController.hoverPathHit) { sceneController.hoveredGlyph = this.sceneModel.glyphAtPoint(point); @@ -138,7 +138,7 @@ export class PointerTool extends BaseTool { point.y -= positionedGlyph.y; const pathHitTester = glyphController.flattenedPathHitTester; const nearestHit = pathHitTester.findNearest(point); - sceneController.magicSelection = [point.x, point.y, nearestHit.x, nearestHit.y]; + sceneController.magicSelectionHit = [point.x, point.y, nearestHit.x, nearestHit.y]; return nearestHit; } diff --git a/src/fontra/views/editor/scene-controller.js b/src/fontra/views/editor/scene-controller.js index 9f4ffdec3..bf10744c5 100644 --- a/src/fontra/views/editor/scene-controller.js +++ b/src/fontra/views/editor/scene-controller.js @@ -831,12 +831,12 @@ export class SceneController { this.canvasController.requestUpdate(); } - get magicSelection() { - return this.sceneModel.magicSelection; + get magicSelectionHit() { + return this.sceneModel.magicSelectionHit; } - set magicSelection(magicSel) { - this.sceneModel.magicSelection = magicSel; + set magicSelectionHit(magicSelHit) { + this.sceneModel.magicSelectionHit = magicSelHit; this.canvasController.requestUpdate(); } diff --git a/src/fontra/views/editor/visualization-layer-definitions.js b/src/fontra/views/editor/visualization-layer-definitions.js index 48dc61096..bcff81d2e 100644 --- a/src/fontra/views/editor/visualization-layer-definitions.js +++ b/src/fontra/views/editor/visualization-layer-definitions.js @@ -1555,14 +1555,14 @@ registerVisualizationLayerDefinition({ lineDash: [10, 10], }, draw: (context, positionedGlyph, parameters, model, controller) => { - if (model.magicSelection === undefined) { + if (model.magicSelectionHit === undefined) { return; } - const selRect = model.magicSelection; - const p1x = selRect[0]; - const p1y = selRect[1]; - const p2x = selRect[2]; - const p2y = selRect[3]; + const magicSelHit = model.magicSelectionHit; + const p1x = magicSelHit[0]; + const p1y = magicSelHit[1]; + const p2x = magicSelHit[2]; + const p2y = magicSelHit[3]; context.lineWidth = parameters.strokeWidth; strokeLineDashed(context, p1x, p1y, p2x, p2y); }, From 01131fee9b7c69cd7c11fbefe129f57caed8f367 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 09:51:51 +0200 Subject: [PATCH 08/19] constraint handleMagicSelect to work only with metaKey pressed --- src/fontra/views/editor/edit-tools-pointer.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index fcbe2ff82..f951db5fc 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -349,10 +349,14 @@ export class PointerTool extends BaseTool { async handleMagicSelect(eventStream, sceneController) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); - for await (const event of eventStream) { - const nearestHit = this.getNearestHit(sceneController, event, glyphController); - const contourIndex = nearestHit.contourIndex; - this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + for await (const event of eventStream) { + if (event.metaKey) { + const nearestHit = this.getNearestHit(sceneController, event, glyphController); + const contourIndex = nearestHit.contourIndex; + this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + } else { + sceneController.magicSelectionHit = undefined; + } } } From f4ce734bdc37859fa5ab0e0f7889a43557b67117 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 09:56:38 +0200 Subject: [PATCH 09/19] magicSelectionHit undefined when mouseUp --- src/fontra/views/editor/edit-tools-pointer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index f951db5fc..0ea6e29f1 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -358,6 +358,7 @@ export class PointerTool extends BaseTool { sceneController.magicSelectionHit = undefined; } } + sceneController.magicSelectionHit = undefined; } async handleDragSelection(eventStream, initialEvent) { From 4f59f942b8985d5a924e8ff51181fc1865dde970 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 10:10:10 +0200 Subject: [PATCH 10/19] cleaned lines spaces --- src/fontra/views/editor/edit-tools-pointer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 0ea6e29f1..caa711f22 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -188,13 +188,13 @@ export class PointerTool extends BaseTool { eventStream.done(); return; } + let initiateDrag = false; let initiateRectSelect = false; const modeFunc = getSelectModeFunction(event); const newSelection = modeFunc(sceneController.selection, selection); const cleanSel = selection; - if ( !selection.size || event.shiftKey || @@ -204,6 +204,7 @@ export class PointerTool extends BaseTool { this._selectionBeforeSingleClick = sceneController.selection; sceneController.selection = newSelection; } + if (isSuperset(sceneController.selection, cleanSel)) { initiateDrag = true; } From eac8b89518d017f13d9248837936fcdf503e5a05 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 10:26:41 +0200 Subject: [PATCH 11/19] magic selection active only on contours --- src/fontra/views/editor/edit-tools-pointer.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index caa711f22..009b312a4 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -136,10 +136,13 @@ export class PointerTool extends BaseTool { const point = sceneController.localPoint(event); point.x -= positionedGlyph.x; point.y -= positionedGlyph.y; - const pathHitTester = glyphController.flattenedPathHitTester; + const pathHitTester = glyphController.pathHitTester; const nearestHit = pathHitTester.findNearest(point); - sceneController.magicSelectionHit = [point.x, point.y, nearestHit.x, nearestHit.y]; - return nearestHit; + if (nearestHit){ + sceneController.magicSelectionHit = [point.x, point.y, nearestHit.x, nearestHit.y]; + const contourIndex = nearestHit.contourIndex; + this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + } } async handleDrag(eventStream, initialEvent) { @@ -204,7 +207,7 @@ export class PointerTool extends BaseTool { this._selectionBeforeSingleClick = sceneController.selection; sceneController.selection = newSelection; } - + if (isSuperset(sceneController.selection, cleanSel)) { initiateDrag = true; } @@ -232,15 +235,11 @@ export class PointerTool extends BaseTool { if (initialEvent.metaKey) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); - const nearestHit = this.getNearestHit(sceneController, initialEvent, glyphController); - const contourIndex = nearestHit.contourIndex; - this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); - + this.getNearestHit(sceneController, initialEvent, glyphController); if (initiateRectSelect){ return await this.handleMagicSelect(eventStream, sceneController); } } else { - sceneController.hoveredGlyph = undefined; if (initiateRectSelect) { return await this.handleRectSelect(eventStream, initialEvent, initialSelection); @@ -352,9 +351,7 @@ export class PointerTool extends BaseTool { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); for await (const event of eventStream) { if (event.metaKey) { - const nearestHit = this.getNearestHit(sceneController, event, glyphController); - const contourIndex = nearestHit.contourIndex; - this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + this.getNearestHit(sceneController, event, glyphController); } else { sceneController.magicSelectionHit = undefined; } From 655dbb9f5b709ebf63cedd095a85b9416d02b41a Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 10:29:07 +0200 Subject: [PATCH 12/19] magicSelectionHit undefined when no nearestHit --- src/fontra/views/editor/edit-tools-pointer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 009b312a4..2ff85a84b 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -142,6 +142,8 @@ export class PointerTool extends BaseTool { sceneController.magicSelectionHit = [point.x, point.y, nearestHit.x, nearestHit.y]; const contourIndex = nearestHit.contourIndex; this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); + } else { + sceneController.magicSelectionHit = undefined; } } From 9083ab7182c9349ed8383ec45fc3a3325db73d31 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 10:52:59 +0200 Subject: [PATCH 13/19] disabled filter on findNearest's results --- src/fontra/client/core/path-hit-tester.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/client/core/path-hit-tester.js b/src/fontra/client/core/path-hit-tester.js index f6c89d448..56d0f7e67 100644 --- a/src/fontra/client/core/path-hit-tester.js +++ b/src/fontra/client/core/path-hit-tester.js @@ -62,7 +62,7 @@ export class PathHitTester { } } - results = results.filter((hit) => hit.t != 0 && hit.t != 1); + // results = results.filter((hit) => hit.t != 0 && hit.t != 1); results.sort((a, b) => a.d - b.d); return results[0]; } From fb0c96783f0b8e6421818bfc7ac9b840062dd479 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 11:20:08 +0200 Subject: [PATCH 14/19] declare magicSelectionHit undefined --- src/fontra/views/editor/edit-tools-pointer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 2ff85a84b..410f357c6 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -58,7 +58,7 @@ export class PointerTool extends BaseTool { sceneController.hoverSelection = selection; sceneController.hoveredGlyph = undefined; sceneController.hoverPathHit = pathHit; - sceneController.magicSelectionHit = []; + sceneController.magicSelectionHit = undefined; if (!sceneController.hoverSelection.size && !sceneController.hoverPathHit) { sceneController.hoveredGlyph = this.sceneModel.glyphAtPoint(point); From f71c2b7f43e3b943d59cea57799374a7df71c35d Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 11:32:37 +0200 Subject: [PATCH 15/19] formatting --- src/fontra/views/editor/edit-tools-pointer.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 410f357c6..4ac170525 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -139,7 +139,12 @@ export class PointerTool extends BaseTool { const pathHitTester = glyphController.pathHitTester; const nearestHit = pathHitTester.findNearest(point); if (nearestHit){ - sceneController.magicSelectionHit = [point.x, point.y, nearestHit.x, nearestHit.y]; + sceneController.magicSelectionHit = [ + point.x, + point.y, + nearestHit.x, + nearestHit.y + ]; const contourIndex = nearestHit.contourIndex; this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); } else { @@ -238,7 +243,7 @@ export class PointerTool extends BaseTool { if (initialEvent.metaKey) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); this.getNearestHit(sceneController, initialEvent, glyphController); - if (initiateRectSelect){ + if (initiateRectSelect) { return await this.handleMagicSelect(eventStream, sceneController); } } else { @@ -351,7 +356,7 @@ export class PointerTool extends BaseTool { async handleMagicSelect(eventStream, sceneController) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); - for await (const event of eventStream) { + for await (const event of eventStream) { if (event.metaKey) { this.getNearestHit(sceneController, event, glyphController); } else { From bae615c816ab1df38be4aefcb131e3f3e3493816 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 11:35:24 +0200 Subject: [PATCH 16/19] formatting --- src/fontra/views/editor/edit-tools-pointer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 4ac170525..448af3cad 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -140,9 +140,9 @@ export class PointerTool extends BaseTool { const nearestHit = pathHitTester.findNearest(point); if (nearestHit){ sceneController.magicSelectionHit = [ - point.x, - point.y, - nearestHit.x, + point.x, + point.y, + nearestHit.x, nearestHit.y ]; const contourIndex = nearestHit.contourIndex; @@ -357,7 +357,7 @@ export class PointerTool extends BaseTool { async handleMagicSelect(eventStream, sceneController) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); for await (const event of eventStream) { - if (event.metaKey) { + if (event.metaKey) { this.getNearestHit(sceneController, event, glyphController); } else { sceneController.magicSelectionHit = undefined; From c588180b43b364f60728b0e420efe832c1b3f470 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 11:37:08 +0200 Subject: [PATCH 17/19] formatting --- src/fontra/views/editor/edit-tools-pointer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 448af3cad..e4aa953ca 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -138,12 +138,12 @@ export class PointerTool extends BaseTool { point.y -= positionedGlyph.y; const pathHitTester = glyphController.pathHitTester; const nearestHit = pathHitTester.findNearest(point); - if (nearestHit){ + if (nearestHit) { sceneController.magicSelectionHit = [ point.x, point.y, nearestHit.x, - nearestHit.y + nearestHit.y, ]; const contourIndex = nearestHit.contourIndex; this.selectContour(sceneController, contourIndex, getMagicSelectModeFunction); From c95d0c3608f26a491834e6040db90d05fd8c0992 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 12:00:00 +0200 Subject: [PATCH 18/19] activate magic selection only when initiate rect select --- src/fontra/views/editor/edit-tools-pointer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index e4aa953ca..40068ce88 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -240,7 +240,7 @@ export class PointerTool extends BaseTool { } } - if (initialEvent.metaKey) { + if (initialEvent.metaKey && initiateRectSelect) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); this.getNearestHit(sceneController, initialEvent, glyphController); if (initiateRectSelect) { From bc1b633fd292ceb863dc9cfc60c411ff94b0f1e5 Mon Sep 17 00:00:00 2001 From: GaetanBaehr Date: Wed, 9 Oct 2024 12:11:24 +0200 Subject: [PATCH 19/19] change to initiate magic selection if not point selected --- src/fontra/views/editor/edit-tools-pointer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/views/editor/edit-tools-pointer.js b/src/fontra/views/editor/edit-tools-pointer.js index 40068ce88..7e1e8f01c 100644 --- a/src/fontra/views/editor/edit-tools-pointer.js +++ b/src/fontra/views/editor/edit-tools-pointer.js @@ -240,7 +240,7 @@ export class PointerTool extends BaseTool { } } - if (initialEvent.metaKey && initiateRectSelect) { + if (initialEvent.metaKey && !initialClickedPointIndex) { const glyphController = await this.sceneModel.getSelectedStaticGlyphController(); this.getNearestHit(sceneController, initialEvent, glyphController); if (initiateRectSelect) {