scratch-paint 4.0.21 → 4.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deploy.yml +3 -3
- package/.github/workflows/update-l10n.yml +2 -2
- package/.nvmrc +1 -1
- package/dist/scratch-paint.js +108 -122
- package/dist/scratch-paint.js.map +1 -1
- package/eslint.config.mjs +61 -0
- package/package.json +6 -8
- package/scripts/build-i18n-source.js +1 -1
- package/src/components/paint-editor/paint-editor.jsx +2 -2
- package/src/containers/mode-tools.jsx +3 -3
- package/src/helper/bit-tools/brush-tool.js +1 -1
- package/src/helper/bit-tools/fill-tool.js +1 -1
- package/src/helper/bit-tools/line-tool.js +3 -3
- package/src/helper/bit-tools/oval-tool.js +1 -1
- package/src/helper/bit-tools/rect-tool.js +1 -1
- package/src/helper/bit-tools/select-tool.js +2 -2
- package/src/helper/bitmap.js +13 -15
- package/src/helper/blob-tools/broad-brush-helper.js +1 -2
- package/src/helper/blob-tools/segment-brush-helper.js +4 -5
- package/src/helper/group.js +14 -16
- package/src/helper/hover.js +1 -1
- package/src/helper/layer.js +5 -5
- package/src/helper/math.js +1 -1
- package/src/helper/selection-tools/bounding-box-tool.js +5 -5
- package/src/helper/selection-tools/handle-tool.js +2 -2
- package/src/helper/selection-tools/move-tool.js +3 -3
- package/src/helper/selection-tools/nudge-tool.js +2 -2
- package/src/helper/selection-tools/point-tool.js +1 -1
- package/src/helper/selection-tools/reshape-tool.js +7 -7
- package/src/helper/selection-tools/rotate-tool.js +1 -1
- package/src/helper/selection-tools/scale-tool.js +3 -3
- package/src/helper/selection-tools/select-tool.js +3 -3
- package/src/helper/selection.js +19 -19
- package/src/helper/snapping.js +2 -2
- package/src/helper/style-path.js +8 -8
- package/src/helper/tools/fill-tool.js +1 -1
- package/src/helper/tools/oval-tool.js +1 -1
- package/src/helper/tools/rect-tool.js +1 -1
- package/src/helper/tools/rounded-rect-tool.js +2 -2
- package/src/helper/tools/text-tool.js +4 -4
- package/src/helper/view.js +9 -10
- package/src/playground/playground.jsx +28 -25
- package/src/playground/reducers/intl.js +1 -2
- package/src/reducers/cursor.js +1 -1
- package/src/reducers/hover.js +1 -1
- package/src/reducers/layout.js +1 -1
- package/src/reducers/selected-items.js +1 -1
- package/src/reducers/text-edit-target.js +1 -1
- package/src/reducers/undo.js +2 -2
- package/src/reducers/view-bounds.js +1 -1
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -3
- package/src/.eslintrc.js +0 -24
- package/tmp.js +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {eslintConfigScratch} from 'eslint-config-scratch';
|
|
2
|
+
import {globalIgnores} from 'eslint/config';
|
|
3
|
+
import globals from 'globals';
|
|
4
|
+
|
|
5
|
+
export default eslintConfigScratch.defineConfig(
|
|
6
|
+
eslintConfigScratch.legacy.base,
|
|
7
|
+
{
|
|
8
|
+
files: [
|
|
9
|
+
'*.{js,cjs,mjs,ts}', // for example, webpack.config.js
|
|
10
|
+
'scripts/**/*.{js,cjs,mjs,ts}'
|
|
11
|
+
],
|
|
12
|
+
extends: [eslintConfigScratch.legacy.node],
|
|
13
|
+
languageOptions: {
|
|
14
|
+
globals: globals.node
|
|
15
|
+
},
|
|
16
|
+
rules: {
|
|
17
|
+
'no-console': 'off'
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
files: ['{src,test}/**/*.{js,cjs,mjs,jsx,ts,tsx}'],
|
|
22
|
+
extends: [
|
|
23
|
+
eslintConfigScratch.legacy.es6,
|
|
24
|
+
eslintConfigScratch.legacy.react
|
|
25
|
+
],
|
|
26
|
+
languageOptions: {
|
|
27
|
+
globals: globals.browser
|
|
28
|
+
},
|
|
29
|
+
rules: {
|
|
30
|
+
// BEGIN: these caused trouble after upgrading eslint-plugin-react from 7.24.0 to 7.33.2
|
|
31
|
+
'react/forbid-prop-types': 'warn',
|
|
32
|
+
'react/no-unknown-property': 'warn',
|
|
33
|
+
// END: these caused trouble after upgrading eslint-plugin-react from 7.24.0 to 7.33.2
|
|
34
|
+
|
|
35
|
+
// we should probably just fix these...
|
|
36
|
+
'react/no-deprecated': 'warn'
|
|
37
|
+
},
|
|
38
|
+
settings: {
|
|
39
|
+
react: {
|
|
40
|
+
version: 'detect'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
files: ['test/**/*.{js,cjs,mjs,jsx,ts,tsx}'],
|
|
46
|
+
extends: [
|
|
47
|
+
eslintConfigScratch.legacy.es6
|
|
48
|
+
],
|
|
49
|
+
languageOptions: {
|
|
50
|
+
globals: {
|
|
51
|
+
...globals.jest,
|
|
52
|
+
...globals.node
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
globalIgnores([
|
|
57
|
+
'dist/**',
|
|
58
|
+
'node_modules/**',
|
|
59
|
+
'playground/**'
|
|
60
|
+
])
|
|
61
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scratch-paint",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.23",
|
|
4
4
|
"description": "Graphical User Interface for the Scratch 3.0 paint editor, which is used to make and edit sprites for use in projects.",
|
|
5
5
|
"main": "./dist/scratch-paint.js",
|
|
6
6
|
"browser": "./src/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"clean": "rimraf ./dist && mkdirp dist && rimraf ./playground && mkdirp playground",
|
|
10
10
|
"i18n:push": "tx-push-src scratch-editor paint-editor ./translations/en.json",
|
|
11
11
|
"i18n:src": "rimraf ./translations/messages && babel src > tmp.js && rimraf tmp.js && ./scripts/build-i18n-source.js ./translations/messages/ ./translations/",
|
|
12
|
-
"lint": "eslint
|
|
12
|
+
"lint": "eslint",
|
|
13
13
|
"start": "webpack-dev-server",
|
|
14
14
|
"test": "npm run unit",
|
|
15
15
|
"unit": "jest --reporters=default",
|
|
@@ -55,18 +55,16 @@
|
|
|
55
55
|
"@commitlint/config-conventional": "17.8.1",
|
|
56
56
|
"@testing-library/react": "8.0.9",
|
|
57
57
|
"autoprefixer": "9.8.8",
|
|
58
|
-
"babel-eslint": "10.1.0",
|
|
59
58
|
"babel-jest": "29.7.0",
|
|
60
59
|
"babel-loader": "8.4.1",
|
|
61
60
|
"babel-plugin-react-intl": "3.5.1",
|
|
62
61
|
"babel-plugin-transform-object-rest-spread": "6.26.0",
|
|
63
62
|
"canvas": "2.11.2",
|
|
64
63
|
"css-loader": "3.6.0",
|
|
65
|
-
"eslint": "
|
|
66
|
-
"eslint-config-scratch": "
|
|
67
|
-
"eslint-plugin-import": "2.32.0",
|
|
68
|
-
"eslint-plugin-react": "7.37.5",
|
|
64
|
+
"eslint": "^9.38.0",
|
|
65
|
+
"eslint-config-scratch": "^12.0.13",
|
|
69
66
|
"gh-pages": "3.2.3",
|
|
67
|
+
"globals": "^16.4.0",
|
|
70
68
|
"html-webpack-plugin": "3.2.0",
|
|
71
69
|
"husky": "8.0.3",
|
|
72
70
|
"jest": "27.5.1",
|
|
@@ -83,7 +81,7 @@
|
|
|
83
81
|
"redux-throttle": "0.1.1",
|
|
84
82
|
"regenerator-runtime": "0.13.9",
|
|
85
83
|
"rimraf": "2.7.1",
|
|
86
|
-
"scratch-l10n": "
|
|
84
|
+
"scratch-l10n": "6.0.69",
|
|
87
85
|
"scratch-semantic-release-config": "4.0.0",
|
|
88
86
|
"semantic-release": "19.0.5",
|
|
89
87
|
"style-loader": "1.3.0",
|
|
@@ -31,7 +31,7 @@ let defaultMessages = glob.sync(MESSAGES_PATTERN)
|
|
|
31
31
|
.map((file) => JSON.parse(file))
|
|
32
32
|
.reduce((collection, descriptors) => {
|
|
33
33
|
descriptors.forEach(({id, defaultMessage, description}) => {
|
|
34
|
-
if (
|
|
34
|
+
if (Object.prototype.hasOwnProperty.call(collection, id)) {
|
|
35
35
|
throw new Error(`Duplicate message id: ${id}`);
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -133,7 +133,7 @@ const PaintEditorComponent = props => {
|
|
|
133
133
|
|
|
134
134
|
<div className={styles.topAlignRow}>
|
|
135
135
|
{/* Modes */}
|
|
136
|
-
{props.canvas !== null && isVector(props.format) ? (
|
|
136
|
+
{props.canvas !== null && isVector(props.format) ? (
|
|
137
137
|
<div className={styles.modeSelector}>
|
|
138
138
|
<SelectMode
|
|
139
139
|
onUpdateImage={props.onUpdateImage}
|
|
@@ -166,7 +166,7 @@ const PaintEditorComponent = props => {
|
|
|
166
166
|
</div>
|
|
167
167
|
) : null}
|
|
168
168
|
|
|
169
|
-
{props.canvas !== null && isBitmap(props.format) ? (
|
|
169
|
+
{props.canvas !== null && isBitmap(props.format) ? (
|
|
170
170
|
<div className={styles.modeSelector}>
|
|
171
171
|
<BitBrushMode
|
|
172
172
|
onUpdateImage={props.onUpdateImage}
|
|
@@ -97,7 +97,7 @@ class ModeTools extends React.Component {
|
|
|
97
97
|
// Point is end point
|
|
98
98
|
// Direction is average of normal at the point and direction to prev point, using the
|
|
99
99
|
// normal that points out from the convex side
|
|
100
|
-
//
|
|
100
|
+
// Length is curve length * HANDLE_RATIO
|
|
101
101
|
const convexity = prev.getCurve().getCurvatureAtTime(.5) < 0 ? -1 : 1;
|
|
102
102
|
point.handleIn = (prev.getCurve().getNormalAtTime(1)
|
|
103
103
|
.multiply(convexity)
|
|
@@ -108,7 +108,7 @@ class ModeTools extends React.Component {
|
|
|
108
108
|
// Point is start point
|
|
109
109
|
// Direction is average of normal at the point and direction to prev point, using the
|
|
110
110
|
// normal that points out from the convex side
|
|
111
|
-
//
|
|
111
|
+
// Length is curve length * HANDLE_RATIO
|
|
112
112
|
const convexity = point.getCurve().getCurvatureAtTime(.5) < 0 ? -1 : 1;
|
|
113
113
|
point.handleOut = (point.getCurve().getNormalAtTime(0)
|
|
114
114
|
.multiply(convexity)
|
|
@@ -236,7 +236,7 @@ ModeTools.propTypes = {
|
|
|
236
236
|
onUpdateImage: PropTypes.func.isRequired,
|
|
237
237
|
// Listen on selected items to update hasSelectedPoints
|
|
238
238
|
selectedItems:
|
|
239
|
-
PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)),
|
|
239
|
+
PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)),
|
|
240
240
|
setSelectedItems: PropTypes.func.isRequired
|
|
241
241
|
};
|
|
242
242
|
|
|
@@ -7,7 +7,7 @@ import {forEachLinePoint, getBrushMark} from '../bitmap';
|
|
|
7
7
|
*/
|
|
8
8
|
class BrushTool extends paper.Tool {
|
|
9
9
|
/**
|
|
10
|
-
* @param {!
|
|
10
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
11
11
|
* @param {boolean} isEraser True if brush should erase
|
|
12
12
|
*/
|
|
13
13
|
constructor (onUpdateImage, isEraser) {
|
|
@@ -10,7 +10,7 @@ const TRANSPARENT = 'rgba(0,0,0,0)';
|
|
|
10
10
|
*/
|
|
11
11
|
class FillTool extends paper.Tool {
|
|
12
12
|
/**
|
|
13
|
-
* @param {!
|
|
13
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
14
14
|
*/
|
|
15
15
|
constructor (onUpdateImage) {
|
|
16
16
|
super();
|
|
@@ -8,12 +8,12 @@ import {ART_BOARD_WIDTH, ART_BOARD_HEIGHT} from '../view';
|
|
|
8
8
|
*/
|
|
9
9
|
class LineTool extends paper.Tool {
|
|
10
10
|
/**
|
|
11
|
-
* @param {!
|
|
11
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
12
12
|
*/
|
|
13
13
|
constructor (onUpdateImage) {
|
|
14
14
|
super();
|
|
15
15
|
this.onUpdateImage = onUpdateImage;
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
// We have to set these functions instead of just declaring them because
|
|
18
18
|
// paper.js tools hook up the listeners in the setter functions.
|
|
19
19
|
this.onMouseMove = this.handleMouseMove;
|
|
@@ -97,7 +97,7 @@ class LineTool extends paper.Tool {
|
|
|
97
97
|
}
|
|
98
98
|
handleMouseUp (event) {
|
|
99
99
|
if (event.event.button > 0 || !this.active) return; // only first mouse button
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
this.drawTarget.remove();
|
|
102
102
|
this.drawTarget = getRaster();
|
|
103
103
|
forEachLinePoint(this.startPoint, event.point, this.draw.bind(this));
|
|
@@ -19,7 +19,7 @@ class OvalTool extends paper.Tool {
|
|
|
19
19
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
20
20
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
21
21
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
22
|
-
* @param {!
|
|
22
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
23
23
|
*/
|
|
24
24
|
constructor (setSelectedItems, clearSelectedItems, setCursor, onUpdateImage) {
|
|
25
25
|
super();
|
|
@@ -19,7 +19,7 @@ class RectTool extends paper.Tool {
|
|
|
19
19
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
20
20
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
21
21
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
22
|
-
* @param {!
|
|
22
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
23
23
|
*/
|
|
24
24
|
constructor (setSelectedItems, clearSelectedItems, setCursor, onUpdateImage) {
|
|
25
25
|
super();
|
|
@@ -24,7 +24,7 @@ class SelectTool extends paper.Tool {
|
|
|
24
24
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
25
25
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
26
26
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
27
|
-
* @param {!
|
|
27
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
28
28
|
*/
|
|
29
29
|
constructor (setSelectedItems, clearSelectedItems, setCursor, onUpdateImage) {
|
|
30
30
|
super();
|
|
@@ -71,7 +71,7 @@ class SelectTool extends paper.Tool {
|
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
73
|
* Returns the hit options to use when conducting hit tests.
|
|
74
|
-
* @
|
|
74
|
+
* @returns {object} See paper.Item.hitTest for definition of options
|
|
75
75
|
*/
|
|
76
76
|
getHitOptions () {
|
|
77
77
|
// Tolerance needs to be scaled when the view is zoomed in in order to represent the same
|
package/src/helper/bitmap.js
CHANGED
|
@@ -38,7 +38,7 @@ const forEachLinePoint = function (point1, point2, callback) {
|
|
|
38
38
|
* @param {!number} a Coefficient in ax^2 + bx + c = 0
|
|
39
39
|
* @param {!number} b Coefficient in ax^2 + bx + c = 0
|
|
40
40
|
* @param {!number} c Coefficient in ax^2 + bx + c = 0
|
|
41
|
-
* @
|
|
41
|
+
* @returns {Array<number>} Array of 2 solutions, with the larger solution first
|
|
42
42
|
*/
|
|
43
43
|
const solveQuadratic_ = function (a, b, c) {
|
|
44
44
|
const soln1 = (-b + Math.sqrt((b * b) - (4 * a * c))) / 2 / a;
|
|
@@ -54,10 +54,10 @@ const solveQuadratic_ = function (a, b, c) {
|
|
|
54
54
|
* @param {!number} options.radiusY minor radius of ellipse
|
|
55
55
|
* @param {!number} options.shearSlope slope of the sheared x axis
|
|
56
56
|
* @param {?boolean} options.isFilled true if isFilled
|
|
57
|
-
* @param {?
|
|
57
|
+
* @param {?Function} options.drawFn The function called on each point in the outline, used only
|
|
58
58
|
* if isFilled is false.
|
|
59
59
|
* @param {!CanvasRenderingContext2D} context for drawing
|
|
60
|
-
* @
|
|
60
|
+
* @returns {boolean} true if anything was drawn, false if not
|
|
61
61
|
*/
|
|
62
62
|
const drawShearedEllipse_ = function (options, context) {
|
|
63
63
|
const centerX = ~~options.centerX;
|
|
@@ -83,8 +83,8 @@ const drawShearedEllipse_ = function (options, context) {
|
|
|
83
83
|
/**
|
|
84
84
|
* Vertical stepping portion of ellipse drawing algorithm
|
|
85
85
|
* @param {!number} startY y to start drawing from
|
|
86
|
-
* @param {!
|
|
87
|
-
* @
|
|
86
|
+
* @param {!Function} conditionFn function which should become true when we should stop stepping
|
|
87
|
+
* @returns {object} last point drawn to the canvas, or null if no points drawn
|
|
88
88
|
*/
|
|
89
89
|
const drawEllipseStepVertical_ = function (startY, conditionFn) {
|
|
90
90
|
// Points on the ellipse
|
|
@@ -114,8 +114,8 @@ const drawShearedEllipse_ = function (options, context) {
|
|
|
114
114
|
/**
|
|
115
115
|
* Horizontal stepping portion of ellipse drawing algorithm
|
|
116
116
|
* @param {!number} startX x to start drawing from
|
|
117
|
-
* @param {!
|
|
118
|
-
* @
|
|
117
|
+
* @param {!Function} conditionFn function which should become false when we should stop stepping
|
|
118
|
+
* @returns {object} last point drawn to the canvas, or null if no points drawn
|
|
119
119
|
*/
|
|
120
120
|
const drawEllipseStepHorizontal_ = function (startX, conditionFn) {
|
|
121
121
|
// Points on the ellipse
|
|
@@ -198,7 +198,7 @@ const drawShearedEllipse_ = function (options, context) {
|
|
|
198
198
|
* @param {!number} size The diameter of the brush
|
|
199
199
|
* @param {!string} color The css color of the brush
|
|
200
200
|
* @param {?boolean} isEraser True if we want the brush mark for the eraser
|
|
201
|
-
* @
|
|
201
|
+
* @returns {HTMLCanvasElement} a canvas with the brush mark printed on it
|
|
202
202
|
*/
|
|
203
203
|
const getBrushMark = function (size, color, isEraser) {
|
|
204
204
|
size = ~~size;
|
|
@@ -251,7 +251,6 @@ const getBrushMark = function (size, color, isEraser) {
|
|
|
251
251
|
* Draw an ellipse, given the original axis-aligned radii and
|
|
252
252
|
* an affine transformation. Returns false if the ellipse could
|
|
253
253
|
* not be drawn; for instance, the matrix is non-invertible.
|
|
254
|
-
*
|
|
255
254
|
* @param {!options} options Parameters for the ellipse
|
|
256
255
|
* @param {!paper.Point} options.position Center of ellipse
|
|
257
256
|
* @param {!number} options.radiusX x-aligned radius of ellipse
|
|
@@ -260,7 +259,7 @@ const getBrushMark = function (size, color, isEraser) {
|
|
|
260
259
|
* @param {?boolean} options.isFilled true if isFilled
|
|
261
260
|
* @param {?number} options.thickness Thickness of outline, used only if isFilled is false.
|
|
262
261
|
* @param {!CanvasRenderingContext2D} context for drawing
|
|
263
|
-
* @
|
|
262
|
+
* @returns {boolean} true if anything was drawn, false if not
|
|
264
263
|
*/
|
|
265
264
|
const drawEllipse = function (options, context) {
|
|
266
265
|
const positionX = options.position.x;
|
|
@@ -508,7 +507,6 @@ const colorPixel_ = function (x, y, imageData, newColor) {
|
|
|
508
507
|
/**
|
|
509
508
|
* Flood fill beginning at the given point.
|
|
510
509
|
* Based on http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
|
|
511
|
-
*
|
|
512
510
|
* @param {!int} x The x coordinate on the context at which to begin
|
|
513
511
|
* @param {!int} y The y coordinate on the context at which to begin
|
|
514
512
|
* @param {!ImageData} sourceImageData The image data to sample from. This is edited by the function.
|
|
@@ -555,7 +553,7 @@ const floodFillInternal_ = function (x, y, sourceImageData, destImageData, newCo
|
|
|
555
553
|
/**
|
|
556
554
|
* Given a fill style string, get the color
|
|
557
555
|
* @param {string} fillStyleString the fill style
|
|
558
|
-
* @
|
|
556
|
+
* @returns {Array<int>} Color, a length 4 array
|
|
559
557
|
*/
|
|
560
558
|
const fillStyleToColor_ = function (fillStyleString) {
|
|
561
559
|
const tmpCanvas = document.createElement('canvas');
|
|
@@ -575,7 +573,7 @@ const fillStyleToColor_ = function (fillStyleString) {
|
|
|
575
573
|
* @param {!HTMLCanvas2DContext} sourceContext The context from which to sample to determine where to flood fill
|
|
576
574
|
* @param {!HTMLCanvas2DContext} destContext The context to which to draw. May match sourceContext. Should match
|
|
577
575
|
* the size of sourceContext.
|
|
578
|
-
* @
|
|
576
|
+
* @returns {boolean} True if image changed, false otherwise
|
|
579
577
|
*/
|
|
580
578
|
const floodFill = function (x, y, color, sourceContext, destContext) {
|
|
581
579
|
x = ~~x;
|
|
@@ -609,7 +607,7 @@ const floodFill = function (x, y, color, sourceContext, destContext) {
|
|
|
609
607
|
* @param {!string} color A color string, which would go into context.fillStyle
|
|
610
608
|
* @param {!HTMLCanvas2DContext} sourceContext The context from which to sample to determine where to flood fill
|
|
611
609
|
* @param {!HTMLCanvas2DContext} destContext The context to which to draw. May match sourceContext. Should match
|
|
612
|
-
* @
|
|
610
|
+
* @returns {boolean} True if image changed, false otherwise
|
|
613
611
|
*/
|
|
614
612
|
const floodFillAll = function (x, y, color, sourceContext, destContext) {
|
|
615
613
|
x = ~~x;
|
|
@@ -887,7 +885,7 @@ const _paperColorToCanvasStyle = function (color, context) {
|
|
|
887
885
|
/**
|
|
888
886
|
* @param {paper.Shape.Ellipse} oval Vector oval to convert
|
|
889
887
|
* @param {paper.Raster} bitmap raster to draw selection
|
|
890
|
-
* @
|
|
888
|
+
* @returns {bool} true if the oval was drawn
|
|
891
889
|
*/
|
|
892
890
|
const commitOvalToBitmap = function (oval, bitmap) {
|
|
893
891
|
const radiusX = Math.abs(oval.size.width / 2);
|
|
@@ -10,7 +10,6 @@ import log from '../../log/log';
|
|
|
10
10
|
* Broad brush draws strokes by drawing points equidistant from the mouse event, perpendicular to the
|
|
11
11
|
* direction of motion. Shortcomings are that this path can cross itself, and 180 degree turns result
|
|
12
12
|
* in a flat edge.
|
|
13
|
-
*
|
|
14
13
|
* @param {!Tool} tool paper.js mouse object
|
|
15
14
|
*/
|
|
16
15
|
class BroadBrushHelper {
|
|
@@ -180,7 +179,7 @@ class BroadBrushHelper {
|
|
|
180
179
|
* Like paper.Path.unite, but it removes the original 2 paths
|
|
181
180
|
* @param {paper.Path} path1 to merge
|
|
182
181
|
* @param {paper.Path} path2 to merge
|
|
183
|
-
* @
|
|
182
|
+
* @returns {paper.Path} merged path. Original paths 1 and 2 will be removed from the view.
|
|
184
183
|
*/
|
|
185
184
|
union (path1, path2) {
|
|
186
185
|
const temp = path1.unite(path2);
|
|
@@ -11,7 +11,6 @@ import {styleBlob} from '../../helper/style-path';
|
|
|
11
11
|
* worse, especially as the number of segments to join increase, and that there are problems in paper.js
|
|
12
12
|
* with union on shapes with curves, so that chunks of the union tend to disappear.
|
|
13
13
|
* (https://github.com/paperjs/paper.js/issues/1321)
|
|
14
|
-
*
|
|
15
14
|
* @param {!Tool} tool paper.js mouse object
|
|
16
15
|
*/
|
|
17
16
|
class SegmentBrushHelper {
|
|
@@ -25,7 +24,7 @@ class SegmentBrushHelper {
|
|
|
25
24
|
|
|
26
25
|
tool.minDistance = 2 / paper.view.zoom;
|
|
27
26
|
tool.maxDistance = options.brushSize;
|
|
28
|
-
|
|
27
|
+
|
|
29
28
|
this.firstCircle = new paper.Path.Circle({
|
|
30
29
|
center: event.point,
|
|
31
30
|
radius: options.brushSize / 2
|
|
@@ -34,7 +33,7 @@ class SegmentBrushHelper {
|
|
|
34
33
|
styleBlob(this.finalPath, options);
|
|
35
34
|
this.lastPoint = event.point;
|
|
36
35
|
}
|
|
37
|
-
|
|
36
|
+
|
|
38
37
|
onSegmentMouseDrag (event, tool, options) {
|
|
39
38
|
if (event.event.button > 0) return; // only first mouse button
|
|
40
39
|
|
|
@@ -44,7 +43,7 @@ class SegmentBrushHelper {
|
|
|
44
43
|
handleVec.angle += 90;
|
|
45
44
|
|
|
46
45
|
const path = new paper.Path();
|
|
47
|
-
|
|
46
|
+
|
|
48
47
|
styleBlob(path, options);
|
|
49
48
|
|
|
50
49
|
// Add handles to round the end caps
|
|
@@ -63,7 +62,7 @@ class SegmentBrushHelper {
|
|
|
63
62
|
// The unite function on curved paths does not always work (sometimes deletes half the path)
|
|
64
63
|
// so we have to flatten.
|
|
65
64
|
path.flatten(Math.min(5, options.brushSize / 5));
|
|
66
|
-
|
|
65
|
+
|
|
67
66
|
this.lastPoint = event.point;
|
|
68
67
|
const newPath = this.finalPath.unite(path);
|
|
69
68
|
path.remove();
|
package/src/helper/group.js
CHANGED
|
@@ -9,10 +9,10 @@ const isGroup = function (item) {
|
|
|
9
9
|
/**
|
|
10
10
|
* Groups the given items. Other things are then deselected and the new group is selected.
|
|
11
11
|
* @param {!Array<paper.Item>} items Root level items to group
|
|
12
|
-
* @param {!
|
|
13
|
-
* @param {!
|
|
14
|
-
* @param {!
|
|
15
|
-
* @
|
|
12
|
+
* @param {!Function} clearSelectedItems Function to clear Redux state's selected items
|
|
13
|
+
* @param {!Function} setSelectedItems Function to set Redux state with new list of selected items
|
|
14
|
+
* @param {!Function} onUpdateImage Function to let listeners know that SVG has changed.
|
|
15
|
+
* @returns {paper.Group} the group if one is created, otherwise false.
|
|
16
16
|
*/
|
|
17
17
|
const groupItems = function (items, clearSelectedItems, setSelectedItems, onUpdateImage) {
|
|
18
18
|
if (items.length > 0) {
|
|
@@ -31,10 +31,10 @@ const groupItems = function (items, clearSelectedItems, setSelectedItems, onUpda
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Groups the selected items. Other things are then deselected and the new group is selected.
|
|
34
|
-
* @param {!
|
|
35
|
-
* @param {!
|
|
36
|
-
* @param {!
|
|
37
|
-
* @
|
|
34
|
+
* @param {!Function} clearSelectedItems Function to clear Redux state's selected items
|
|
35
|
+
* @param {!Function} setSelectedItems Function to set Redux state with new list of selected items
|
|
36
|
+
* @param {!Function} onUpdateImage Function to let listeners know that SVG has changed.
|
|
37
|
+
* @returns {paper.Group} the group if one is created, otherwise false.
|
|
38
38
|
*/
|
|
39
39
|
const groupSelection = function (clearSelectedItems, setSelectedItems, onUpdateImage) {
|
|
40
40
|
const items = getSelectedRootItems();
|
|
@@ -44,7 +44,7 @@ const groupSelection = function (clearSelectedItems, setSelectedItems, onUpdateI
|
|
|
44
44
|
const _ungroupLoop = function (group, recursive, setSelectedItems) {
|
|
45
45
|
// Can't ungroup items that are not groups
|
|
46
46
|
if (!group || !group.children || !isGroup(group)) return;
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
group.applyMatrix = true;
|
|
49
49
|
// iterate over group children recursively
|
|
50
50
|
for (let i = 0; i < group.children.length; i++) {
|
|
@@ -74,10 +74,9 @@ const _ungroupLoop = function (group, recursive, setSelectedItems) {
|
|
|
74
74
|
* onUpdateImage is called to notify listeners of a change on the SVG only if onUpdateImage is passed in.
|
|
75
75
|
* The reason these arguments are optional on ungroupItems is because ungroupItems is used for parts of
|
|
76
76
|
* SVG import, which shouldn't change the selection or undo state.
|
|
77
|
-
*
|
|
78
77
|
* @param {!Array<paper.Item>} items Items to ungroup if they are groups
|
|
79
|
-
* @param {?
|
|
80
|
-
* @param {?
|
|
78
|
+
* @param {?Function} setSelectedItems Function to set Redux state with new list of selected items
|
|
79
|
+
* @param {?Function} onUpdateImage Function to let listeners know that SVG has changed.
|
|
81
80
|
*/
|
|
82
81
|
const ungroupItems = function (items, setSelectedItems, onUpdateImage) {
|
|
83
82
|
if (items.length === 0) {
|
|
@@ -111,10 +110,9 @@ const ungroupItems = function (items, setSelectedItems, onUpdateImage) {
|
|
|
111
110
|
|
|
112
111
|
/**
|
|
113
112
|
* Ungroups the selected items. Other items are deselected and the ungrouped items are selected.
|
|
114
|
-
*
|
|
115
|
-
* @param {!
|
|
116
|
-
* @param {!
|
|
117
|
-
* @param {!function} onUpdateImage Function to let listeners know that SVG has changed.
|
|
113
|
+
* @param {!Function} clearSelectedItems Function to clear Redux state's selected items
|
|
114
|
+
* @param {!Function} setSelectedItems Function to set Redux state with new list of selected items
|
|
115
|
+
* @param {!Function} onUpdateImage Function to let listeners know that SVG has changed.
|
|
118
116
|
*/
|
|
119
117
|
const ungroupSelection = function (clearSelectedItems, setSelectedItems, onUpdateImage) {
|
|
120
118
|
const items = getSelectedRootItems();
|
package/src/helper/hover.js
CHANGED
|
@@ -9,7 +9,7 @@ import {sortItemsByZIndex} from './math';
|
|
|
9
9
|
* @param {?object} hitOptions hit options to use
|
|
10
10
|
* @param {?boolean} subselect Whether items within groups can be hovered. If false, the
|
|
11
11
|
* entire group should be hovered.
|
|
12
|
-
* @
|
|
12
|
+
* @returns {paper.Item} the hovered item or null if there is none
|
|
13
13
|
*/
|
|
14
14
|
const getHoveredItem = function (event, hitOptions, subselect) {
|
|
15
15
|
const oldMatch = hitOptions.match;
|
package/src/helper/layer.js
CHANGED
|
@@ -24,7 +24,7 @@ const _getPaintingLayer = function () {
|
|
|
24
24
|
* Creates a canvas with width and height matching the art board size.
|
|
25
25
|
* @param {?number} width Width of the canvas. Defaults to ART_BOARD_WIDTH.
|
|
26
26
|
* @param {?number} height Height of the canvas. Defaults to ART_BOARD_HEIGHT.
|
|
27
|
-
* @
|
|
27
|
+
* @returns {HTMLCanvasElement} the canvas
|
|
28
28
|
*/
|
|
29
29
|
const createCanvas = function (width, height) {
|
|
30
30
|
const canvas = document.createElement('canvas');
|
|
@@ -37,7 +37,7 @@ const createCanvas = function (width, height) {
|
|
|
37
37
|
const clearRaster = function () {
|
|
38
38
|
const layer = _getLayer('isRasterLayer');
|
|
39
39
|
layer.removeChildren();
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
// Generate blank raster
|
|
42
42
|
const raster = new paper.Raster(createCanvas());
|
|
43
43
|
raster.canvas.getContext('2d').imageSmoothingEnabled = false;
|
|
@@ -101,7 +101,7 @@ const setGuideItem = function (item) {
|
|
|
101
101
|
/**
|
|
102
102
|
* Removes the guide layers, e.g. for purposes of exporting the image. Must call showGuideLayers to re-add them.
|
|
103
103
|
* @param {boolean} includeRaster true if the raster layer should also be hidden
|
|
104
|
-
* @
|
|
104
|
+
* @returns {object} an object of the removed layers, which should be passed to showGuideLayers to re-add them.
|
|
105
105
|
*/
|
|
106
106
|
const hideGuideLayers = function (includeRaster) {
|
|
107
107
|
const backgroundGuideLayer = getBackgroundGuideLayer();
|
|
@@ -288,7 +288,7 @@ const _makeOutlineLayer = function () {
|
|
|
288
288
|
const _makeBackgroundGuideLayer = function (format) {
|
|
289
289
|
const guideLayer = new paper.Layer();
|
|
290
290
|
guideLayer.locked = true;
|
|
291
|
-
|
|
291
|
+
|
|
292
292
|
const vWorkspaceBounds = new paper.Shape.Rectangle(MAX_WORKSPACE_BOUNDS);
|
|
293
293
|
vWorkspaceBounds.fillColor = '#ECF1F9';
|
|
294
294
|
vWorkspaceBounds.position = CENTER;
|
|
@@ -319,7 +319,7 @@ const _makeBackgroundGuideLayer = function (format) {
|
|
|
319
319
|
guideLayer.bitmapBackground = bitmapBackground;
|
|
320
320
|
|
|
321
321
|
_convertLayer(guideLayer, format);
|
|
322
|
-
|
|
322
|
+
|
|
323
323
|
_makeCrosshair(0.16, guideLayer);
|
|
324
324
|
|
|
325
325
|
guideLayer.data.isBackgroundGuideLayer = true;
|
package/src/helper/math.js
CHANGED
|
@@ -137,7 +137,7 @@ const scaleWithStrokes = function (root, factor, pivot) {
|
|
|
137
137
|
* for shapes like circles ("square ovals"), which fill the same dimensions.)
|
|
138
138
|
* @param {!paper.Point} startPos The point where the user started dragging
|
|
139
139
|
* @param {!paper.Point} eventPoint The point where the user has currently dragged to
|
|
140
|
-
* @
|
|
140
|
+
* @returns {object} Information about the size and position of how the square should be drawn
|
|
141
141
|
*/
|
|
142
142
|
const getSquareDimensions = function (startPos, eventPoint) {
|
|
143
143
|
// These variables are used for determining the relative quadrant that the shape will appear in.
|
|
@@ -30,7 +30,7 @@ const BoundingBoxModes = keyMirror({
|
|
|
30
30
|
* On mouse down, the type of function (move, scale, rotate) is determined based on what is clicked
|
|
31
31
|
* (scale handle, rotate handle, the object itself). This determines the mode of the tool, which then
|
|
32
32
|
* delegates actions to the MoveTool, RotateTool or ScaleTool accordingly.
|
|
33
|
-
* @param {!
|
|
33
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
34
34
|
*/
|
|
35
35
|
class BoundingBoxTool {
|
|
36
36
|
/**
|
|
@@ -38,8 +38,8 @@ class BoundingBoxTool {
|
|
|
38
38
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
39
39
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
40
40
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
41
|
-
* @param {!
|
|
42
|
-
* @param {?
|
|
41
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
42
|
+
* @param {?Function} switchToTextTool A callback to call to switch to the text tool
|
|
43
43
|
*/
|
|
44
44
|
constructor (mode, setSelectedItems, clearSelectedItems, setCursor, onUpdateImage, switchToTextTool) {
|
|
45
45
|
this.dispatchSetCursor = setCursor;
|
|
@@ -72,10 +72,10 @@ class BoundingBoxTool {
|
|
|
72
72
|
* @param {!MouseEvent} event The mouse event
|
|
73
73
|
* @param {boolean} clone Whether to clone on mouse down (e.g. alt key held)
|
|
74
74
|
* @param {boolean} multiselect Whether to multiselect on mouse down (e.g. shift key held)
|
|
75
|
-
* @param {?boolean} doubleClicked True if this is the second click in a short
|
|
75
|
+
* @param {?boolean} doubleClicked True if this is the second click in a short amount of time
|
|
76
76
|
* @param {paper.hitOptions} hitOptions The options with which to detect whether mouse down has hit
|
|
77
77
|
* anything editable
|
|
78
|
-
* @
|
|
78
|
+
* @returns {boolean} True if there was a hit, false otherwise
|
|
79
79
|
*/
|
|
80
80
|
onMouseDown (event, clone, multiselect, doubleClicked, hitOptions) {
|
|
81
81
|
if (event.event.button > 0) return; // only first mouse button
|
|
@@ -5,7 +5,7 @@ class HandleTool {
|
|
|
5
5
|
/**
|
|
6
6
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
7
7
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
8
|
-
* @param {!
|
|
8
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
9
9
|
*/
|
|
10
10
|
constructor (setSelectedItems, clearSelectedItems, onUpdateImage) {
|
|
11
11
|
this.hitType = null;
|
|
@@ -23,7 +23,7 @@ class HandleTool {
|
|
|
23
23
|
if (!hitProperties.multiselect) {
|
|
24
24
|
clearSelection(this.clearSelectedItems);
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
hitProperties.hitResult.segment.handleIn.selected = true;
|
|
28
28
|
hitProperties.hitResult.segment.handleOut.selected = true;
|
|
29
29
|
this.hitType = hitProperties.hitResult.type;
|
|
@@ -21,8 +21,8 @@ class MoveTool {
|
|
|
21
21
|
* @param {Modes} mode Paint editor mode
|
|
22
22
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
23
23
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
24
|
-
* @param {!
|
|
25
|
-
* @param {?
|
|
24
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
25
|
+
* @param {?Function} switchToTextTool A callback to call to switch to the text tool
|
|
26
26
|
*/
|
|
27
27
|
constructor (mode, setSelectedItems, clearSelectedItems, onUpdateImage, switchToTextTool) {
|
|
28
28
|
this.mode = mode;
|
|
@@ -41,7 +41,7 @@ class MoveTool {
|
|
|
41
41
|
* @param {!paper.HitResult} hitProperties.hitResult Data about the location of the mouse click
|
|
42
42
|
* @param {?boolean} hitProperties.clone Whether to clone on mouse down (e.g. alt key held)
|
|
43
43
|
* @param {?boolean} hitProperties.multiselect Whether to multiselect on mouse down (e.g. shift key held)
|
|
44
|
-
* @param {?boolean} hitProperties.doubleClicked True if this is the second click in a short
|
|
44
|
+
* @param {?boolean} hitProperties.doubleClicked True if this is the second click in a short amount of time
|
|
45
45
|
* @param {?boolean} hitProperties.subselect True if we allow selection of subgroups, false if we should
|
|
46
46
|
* select the whole group.
|
|
47
47
|
*/
|
|
@@ -13,7 +13,7 @@ class NudgeTool {
|
|
|
13
13
|
/**
|
|
14
14
|
* @param {Mode} mode Paint editor mode
|
|
15
15
|
* @param {function} boundingBoxTool to control the bounding box
|
|
16
|
-
* @param {!
|
|
16
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
17
17
|
*/
|
|
18
18
|
constructor (mode, boundingBoxTool, onUpdateImage) {
|
|
19
19
|
this.boundingBoxTool = boundingBoxTool;
|
|
@@ -31,7 +31,7 @@ class NudgeTool {
|
|
|
31
31
|
|
|
32
32
|
const selected = getSelectedRootItems();
|
|
33
33
|
if (selected.length === 0) return;
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
// Get bounds. Don't let item bounds go out of bounds.
|
|
36
36
|
let rect;
|
|
37
37
|
for (const item of selected) {
|