@nasser-sw/fabric 7.0.1-beta1 → 7.0.1-beta3
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/dist/index.js +504 -102
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +504 -102
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +504 -102
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +504 -102
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.json.min.mjs +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/shapes/Polyline.d.ts +7 -0
- package/dist/src/shapes/Polyline.d.ts.map +1 -1
- package/dist/src/shapes/Polyline.min.mjs +1 -1
- package/dist/src/shapes/Polyline.min.mjs.map +1 -1
- package/dist/src/shapes/Polyline.mjs +48 -16
- package/dist/src/shapes/Polyline.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist/src/shapes/Text/Text.min.mjs +1 -1
- package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.mjs +64 -12
- package/dist/src/shapes/Text/Text.mjs.map +1 -1
- package/dist/src/shapes/Textbox.d.ts.map +1 -1
- package/dist/src/shapes/Textbox.min.mjs +1 -1
- package/dist/src/shapes/Textbox.min.mjs.map +1 -1
- package/dist/src/shapes/Textbox.mjs +2 -52
- package/dist/src/shapes/Textbox.mjs.map +1 -1
- package/dist/src/shapes/Triangle.d.ts +27 -2
- package/dist/src/shapes/Triangle.d.ts.map +1 -1
- package/dist/src/shapes/Triangle.min.mjs +1 -1
- package/dist/src/shapes/Triangle.min.mjs.map +1 -1
- package/dist/src/shapes/Triangle.mjs +72 -12
- package/dist/src/shapes/Triangle.mjs.map +1 -1
- package/dist/src/text/overlayEditor.d.ts.map +1 -1
- package/dist/src/text/overlayEditor.min.mjs +1 -1
- package/dist/src/text/overlayEditor.min.mjs.map +1 -1
- package/dist/src/text/overlayEditor.mjs +143 -9
- package/dist/src/text/overlayEditor.mjs.map +1 -1
- package/dist/src/util/misc/cornerRadius.d.ts +70 -0
- package/dist/src/util/misc/cornerRadius.d.ts.map +1 -0
- package/dist/src/util/misc/cornerRadius.min.mjs +2 -0
- package/dist/src/util/misc/cornerRadius.min.mjs.map +1 -0
- package/dist/src/util/misc/cornerRadius.mjs +181 -0
- package/dist/src/util/misc/cornerRadius.mjs.map +1 -0
- package/dist-extensions/src/shapes/Polyline.d.ts +7 -0
- package/dist-extensions/src/shapes/Polyline.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Triangle.d.ts +27 -2
- package/dist-extensions/src/shapes/Triangle.d.ts.map +1 -1
- package/dist-extensions/src/text/overlayEditor.d.ts.map +1 -1
- package/dist-extensions/src/util/misc/cornerRadius.d.ts +70 -0
- package/dist-extensions/src/util/misc/cornerRadius.d.ts.map +1 -0
- package/fabric-test-editor.html +1048 -0
- package/package.json +164 -164
- package/src/shapes/Polyline.ts +70 -29
- package/src/shapes/Text/Text.ts +79 -14
- package/src/shapes/Textbox.ts +1 -1
- package/src/shapes/Triangle.spec.ts +76 -0
- package/src/shapes/Triangle.ts +85 -15
- package/src/text/overlayEditor.ts +152 -12
- package/src/util/misc/cornerRadius.spec.ts +141 -0
- package/src/util/misc/cornerRadius.ts +269 -0
package/package.json
CHANGED
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nasser-sw/fabric",
|
|
3
|
-
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
|
|
4
|
-
"homepage": "http://fabricjs.com/",
|
|
5
|
-
"version": "7.0.1-
|
|
6
|
-
"author": "Juriy Zaytsev <kangax@gmail.com>",
|
|
7
|
-
"contributors": [
|
|
8
|
-
{
|
|
9
|
-
"name": "Andrea Bogazzi",
|
|
10
|
-
"email": "andreabogazzi79@gmail.com",
|
|
11
|
-
"url": "https://github.com/asturur"
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"name": "Shachar Nencel",
|
|
15
|
-
"email": "shacharnen@gmail.com",
|
|
16
|
-
"url": "https://github.com/ShaMan123"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"name": "Steve Eberhardt",
|
|
20
|
-
"email": "melchiar2@gmail.com",
|
|
21
|
-
"url": "https://github.com/melchiar"
|
|
22
|
-
}
|
|
23
|
-
],
|
|
24
|
-
"keywords": [
|
|
25
|
-
"canvas",
|
|
26
|
-
"graphic",
|
|
27
|
-
"graphics",
|
|
28
|
-
"SVG",
|
|
29
|
-
"node-canvas",
|
|
30
|
-
"parser",
|
|
31
|
-
"HTML5",
|
|
32
|
-
"object model"
|
|
33
|
-
],
|
|
34
|
-
"publishConfig": {
|
|
35
|
-
"access": "public"
|
|
36
|
-
},
|
|
37
|
-
"repository": {
|
|
38
|
-
"type": "git",
|
|
39
|
-
"url": "https://github.com/fabricjs/fabric.js"
|
|
40
|
-
},
|
|
41
|
-
"bugs": {
|
|
42
|
-
"url": "https://github.com/fabricjs/fabric.js/issues"
|
|
43
|
-
},
|
|
44
|
-
"license": "MIT",
|
|
45
|
-
"scripts": {
|
|
46
|
-
"docs": "typedoc",
|
|
47
|
-
"cli": "node ./scripts/index.mjs",
|
|
48
|
-
"sandboxscript": "node ./scripts/sandbox.mjs",
|
|
49
|
-
"build": "npm run cli -- build",
|
|
50
|
-
"build:fast": "npm run build -- -f",
|
|
51
|
-
"dev": "npm run cli -- dev",
|
|
52
|
-
"start": "npm run sandboxscript -- start",
|
|
53
|
-
"export": "npm run cli -- website export",
|
|
54
|
-
"test:vitest": "vitest --run --project unit-node",
|
|
55
|
-
"test:vitest:chromium": "vitest --run --project unit-chromium",
|
|
56
|
-
"test:vitest:firefox": "vitest --run --project unit-firefox",
|
|
57
|
-
"test:vitest:all": "vitest --run",
|
|
58
|
-
"test:vitest:coverage": "vitest --run --coverage --project unit-node",
|
|
59
|
-
"test:vitest:coverage:watch": "npm run test:vitest --coverage=true",
|
|
60
|
-
"coverage:merge": "nyc merge coveragefiles .nyc_output/merged-coverage.json",
|
|
61
|
-
"coverage:report": "nyc report --skip-full=true --reporter=lcov --reporter=text --reporter=text-summary",
|
|
62
|
-
"coverage:report:ci": "nyc report --reporter=text-summary",
|
|
63
|
-
"test:e2e": "npm run playwright:typecheck && playwright test",
|
|
64
|
-
"playwright:typecheck": "tsc -p ./e2e/tsconfig.json --noEmit",
|
|
65
|
-
"sandbox": "npm run sandboxscript -- sandbox",
|
|
66
|
-
"local-server": "serve ./ -l tcp://localhost:8080",
|
|
67
|
-
"lint": "eslint src extensions",
|
|
68
|
-
"prettier:check": "prettier --check .",
|
|
69
|
-
"prettier:write": "prettier --write ."
|
|
70
|
-
},
|
|
71
|
-
"devDependencies": {
|
|
72
|
-
"@babel/cli": "^7.28.3",
|
|
73
|
-
"@babel/core": "^7.28.3",
|
|
74
|
-
"@babel/preset-env": "^7.28.3",
|
|
75
|
-
"@babel/preset-typescript": "^7.27.1",
|
|
76
|
-
"@eslint/js": "^9.31.0",
|
|
77
|
-
"@playwright/test": "^1.55.0",
|
|
78
|
-
"@rollup/plugin-babel": "^6.0.4",
|
|
79
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
80
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
81
|
-
"@rollup/plugin-typescript": "^12.1.4",
|
|
82
|
-
"@types/fs-extra": "^11.0.4",
|
|
83
|
-
"@types/jsdom": "^21.1.7",
|
|
84
|
-
"@types/micromatch": "^4.0.9",
|
|
85
|
-
"@types/node": "^24.3.0",
|
|
86
|
-
"@vitest/browser": "^3.2.4",
|
|
87
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
88
|
-
"@vitest/ui": "^3.2.4",
|
|
89
|
-
"babel-plugin-transform-imports": "git+https://git@github.com/fabricjs/babel-plugin-transform-imports.git",
|
|
90
|
-
"chalk": "^5.6.0",
|
|
91
|
-
"commander": "^14.0.0",
|
|
92
|
-
"es-toolkit": "1.39.7",
|
|
93
|
-
"eslint-config-prettier": "^10.1.8",
|
|
94
|
-
"fs-extra": "^11.3.1",
|
|
95
|
-
"inquirer": "^12.9.4",
|
|
96
|
-
"micromatch": "^4.0.8",
|
|
97
|
-
"moment": "^2.30.1",
|
|
98
|
-
"nyc": "^17.1.0",
|
|
99
|
-
"prettier": "^3.6.2",
|
|
100
|
-
"ps-list": "^8.1.1",
|
|
101
|
-
"rollup": "^4.48.0",
|
|
102
|
-
"semver": "^7.7.2",
|
|
103
|
-
"serve": "^14.2.4",
|
|
104
|
-
"tslib": "^2.8.1",
|
|
105
|
-
"typescript": "^5.9.2",
|
|
106
|
-
"typescript-eslint": "^8.40.0",
|
|
107
|
-
"v8-to-istanbul": "^9.3.0",
|
|
108
|
-
"vite": "^6.3.5",
|
|
109
|
-
"vitest": "^3.2.4"
|
|
110
|
-
},
|
|
111
|
-
"engines": {
|
|
112
|
-
"node": ">=18.0.0"
|
|
113
|
-
},
|
|
114
|
-
"overrides": {
|
|
115
|
-
"canvas": {
|
|
116
|
-
"canvas": "3.2.0"
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
"module": "./dist/index.mjs",
|
|
120
|
-
"types": "./dist/index.d.ts",
|
|
121
|
-
"typesVersions": {
|
|
122
|
-
">=4.2": {
|
|
123
|
-
"*": [
|
|
124
|
-
"dist/index.d.ts"
|
|
125
|
-
],
|
|
126
|
-
"node": [
|
|
127
|
-
"dist/index.node.d.ts"
|
|
128
|
-
]
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
"sideEffects": false,
|
|
132
|
-
"exports": {
|
|
133
|
-
".": {
|
|
134
|
-
"types": "./dist/index.d.ts",
|
|
135
|
-
"import": "./dist/index.min.mjs",
|
|
136
|
-
"require": "./dist/index.min.js",
|
|
137
|
-
"default": "./dist/index.min.js"
|
|
138
|
-
},
|
|
139
|
-
"./es": {
|
|
140
|
-
"types": "./dist/index.d.ts",
|
|
141
|
-
"import": "./dist/fabric.min.mjs",
|
|
142
|
-
"require": null,
|
|
143
|
-
"default": null
|
|
144
|
-
},
|
|
145
|
-
"./node": {
|
|
146
|
-
"node": "./dist/index.node.cjs",
|
|
147
|
-
"types": "./dist/index.node.d.ts",
|
|
148
|
-
"import": "./dist/index.node.mjs",
|
|
149
|
-
"require": "./dist/index.node.cjs",
|
|
150
|
-
"default": "./dist/index.node.cjs"
|
|
151
|
-
},
|
|
152
|
-
"./extensions": {
|
|
153
|
-
"node": "./dist-extensions/index.mjs",
|
|
154
|
-
"types": "./dist-extensions/extensions/index.d.ts",
|
|
155
|
-
"import": "./dist-extensions/index.mjs",
|
|
156
|
-
"require": null,
|
|
157
|
-
"default": "./dist-extensions/fabric-extensions.min.js"
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
"optionalDependencies": {
|
|
161
|
-
"canvas": "^3.2.0",
|
|
162
|
-
"jsdom": "^26.1.0"
|
|
163
|
-
}
|
|
164
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@nasser-sw/fabric",
|
|
3
|
+
"description": "Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.",
|
|
4
|
+
"homepage": "http://fabricjs.com/",
|
|
5
|
+
"version": "7.0.1-beta3",
|
|
6
|
+
"author": "Juriy Zaytsev <kangax@gmail.com>",
|
|
7
|
+
"contributors": [
|
|
8
|
+
{
|
|
9
|
+
"name": "Andrea Bogazzi",
|
|
10
|
+
"email": "andreabogazzi79@gmail.com",
|
|
11
|
+
"url": "https://github.com/asturur"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Shachar Nencel",
|
|
15
|
+
"email": "shacharnen@gmail.com",
|
|
16
|
+
"url": "https://github.com/ShaMan123"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "Steve Eberhardt",
|
|
20
|
+
"email": "melchiar2@gmail.com",
|
|
21
|
+
"url": "https://github.com/melchiar"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"keywords": [
|
|
25
|
+
"canvas",
|
|
26
|
+
"graphic",
|
|
27
|
+
"graphics",
|
|
28
|
+
"SVG",
|
|
29
|
+
"node-canvas",
|
|
30
|
+
"parser",
|
|
31
|
+
"HTML5",
|
|
32
|
+
"object model"
|
|
33
|
+
],
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/fabricjs/fabric.js"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/fabricjs/fabric.js/issues"
|
|
43
|
+
},
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"scripts": {
|
|
46
|
+
"docs": "typedoc",
|
|
47
|
+
"cli": "node ./scripts/index.mjs",
|
|
48
|
+
"sandboxscript": "node ./scripts/sandbox.mjs",
|
|
49
|
+
"build": "npm run cli -- build",
|
|
50
|
+
"build:fast": "npm run build -- -f",
|
|
51
|
+
"dev": "npm run cli -- dev",
|
|
52
|
+
"start": "npm run sandboxscript -- start",
|
|
53
|
+
"export": "npm run cli -- website export",
|
|
54
|
+
"test:vitest": "vitest --run --project unit-node",
|
|
55
|
+
"test:vitest:chromium": "vitest --run --project unit-chromium",
|
|
56
|
+
"test:vitest:firefox": "vitest --run --project unit-firefox",
|
|
57
|
+
"test:vitest:all": "vitest --run",
|
|
58
|
+
"test:vitest:coverage": "vitest --run --coverage --project unit-node",
|
|
59
|
+
"test:vitest:coverage:watch": "npm run test:vitest --coverage=true",
|
|
60
|
+
"coverage:merge": "nyc merge coveragefiles .nyc_output/merged-coverage.json",
|
|
61
|
+
"coverage:report": "nyc report --skip-full=true --reporter=lcov --reporter=text --reporter=text-summary",
|
|
62
|
+
"coverage:report:ci": "nyc report --reporter=text-summary",
|
|
63
|
+
"test:e2e": "npm run playwright:typecheck && playwright test",
|
|
64
|
+
"playwright:typecheck": "tsc -p ./e2e/tsconfig.json --noEmit",
|
|
65
|
+
"sandbox": "npm run sandboxscript -- sandbox",
|
|
66
|
+
"local-server": "serve ./ -l tcp://localhost:8080",
|
|
67
|
+
"lint": "eslint src extensions",
|
|
68
|
+
"prettier:check": "prettier --check .",
|
|
69
|
+
"prettier:write": "prettier --write ."
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@babel/cli": "^7.28.3",
|
|
73
|
+
"@babel/core": "^7.28.3",
|
|
74
|
+
"@babel/preset-env": "^7.28.3",
|
|
75
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
76
|
+
"@eslint/js": "^9.31.0",
|
|
77
|
+
"@playwright/test": "^1.55.0",
|
|
78
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
79
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
80
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
81
|
+
"@rollup/plugin-typescript": "^12.1.4",
|
|
82
|
+
"@types/fs-extra": "^11.0.4",
|
|
83
|
+
"@types/jsdom": "^21.1.7",
|
|
84
|
+
"@types/micromatch": "^4.0.9",
|
|
85
|
+
"@types/node": "^24.3.0",
|
|
86
|
+
"@vitest/browser": "^3.2.4",
|
|
87
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
88
|
+
"@vitest/ui": "^3.2.4",
|
|
89
|
+
"babel-plugin-transform-imports": "git+https://git@github.com/fabricjs/babel-plugin-transform-imports.git",
|
|
90
|
+
"chalk": "^5.6.0",
|
|
91
|
+
"commander": "^14.0.0",
|
|
92
|
+
"es-toolkit": "1.39.7",
|
|
93
|
+
"eslint-config-prettier": "^10.1.8",
|
|
94
|
+
"fs-extra": "^11.3.1",
|
|
95
|
+
"inquirer": "^12.9.4",
|
|
96
|
+
"micromatch": "^4.0.8",
|
|
97
|
+
"moment": "^2.30.1",
|
|
98
|
+
"nyc": "^17.1.0",
|
|
99
|
+
"prettier": "^3.6.2",
|
|
100
|
+
"ps-list": "^8.1.1",
|
|
101
|
+
"rollup": "^4.48.0",
|
|
102
|
+
"semver": "^7.7.2",
|
|
103
|
+
"serve": "^14.2.4",
|
|
104
|
+
"tslib": "^2.8.1",
|
|
105
|
+
"typescript": "^5.9.2",
|
|
106
|
+
"typescript-eslint": "^8.40.0",
|
|
107
|
+
"v8-to-istanbul": "^9.3.0",
|
|
108
|
+
"vite": "^6.3.5",
|
|
109
|
+
"vitest": "^3.2.4"
|
|
110
|
+
},
|
|
111
|
+
"engines": {
|
|
112
|
+
"node": ">=18.0.0"
|
|
113
|
+
},
|
|
114
|
+
"overrides": {
|
|
115
|
+
"canvas": {
|
|
116
|
+
"canvas": "3.2.0"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"module": "./dist/index.mjs",
|
|
120
|
+
"types": "./dist/index.d.ts",
|
|
121
|
+
"typesVersions": {
|
|
122
|
+
">=4.2": {
|
|
123
|
+
"*": [
|
|
124
|
+
"dist/index.d.ts"
|
|
125
|
+
],
|
|
126
|
+
"node": [
|
|
127
|
+
"dist/index.node.d.ts"
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"sideEffects": false,
|
|
132
|
+
"exports": {
|
|
133
|
+
".": {
|
|
134
|
+
"types": "./dist/index.d.ts",
|
|
135
|
+
"import": "./dist/index.min.mjs",
|
|
136
|
+
"require": "./dist/index.min.js",
|
|
137
|
+
"default": "./dist/index.min.js"
|
|
138
|
+
},
|
|
139
|
+
"./es": {
|
|
140
|
+
"types": "./dist/index.d.ts",
|
|
141
|
+
"import": "./dist/fabric.min.mjs",
|
|
142
|
+
"require": null,
|
|
143
|
+
"default": null
|
|
144
|
+
},
|
|
145
|
+
"./node": {
|
|
146
|
+
"node": "./dist/index.node.cjs",
|
|
147
|
+
"types": "./dist/index.node.d.ts",
|
|
148
|
+
"import": "./dist/index.node.mjs",
|
|
149
|
+
"require": "./dist/index.node.cjs",
|
|
150
|
+
"default": "./dist/index.node.cjs"
|
|
151
|
+
},
|
|
152
|
+
"./extensions": {
|
|
153
|
+
"node": "./dist-extensions/index.mjs",
|
|
154
|
+
"types": "./dist-extensions/extensions/index.d.ts",
|
|
155
|
+
"import": "./dist-extensions/index.mjs",
|
|
156
|
+
"require": null,
|
|
157
|
+
"default": "./dist-extensions/fabric-extensions.min.js"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"optionalDependencies": {
|
|
161
|
+
"canvas": "^3.2.0",
|
|
162
|
+
"jsdom": "^26.1.0"
|
|
163
|
+
}
|
|
164
|
+
}
|
package/src/shapes/Polyline.ts
CHANGED
|
@@ -25,16 +25,23 @@ import {
|
|
|
25
25
|
TOP,
|
|
26
26
|
} from '../constants';
|
|
27
27
|
import type { CSSRules } from '../parser/typedefs';
|
|
28
|
+
import {
|
|
29
|
+
applyCornerRadiusToPolygon,
|
|
30
|
+
renderRoundedPolygon,
|
|
31
|
+
generateRoundedPolygonPath,
|
|
32
|
+
} from '../util/misc/cornerRadius';
|
|
28
33
|
|
|
29
34
|
export const polylineDefaultValues: Partial<TClassProperties<Polyline>> = {
|
|
30
35
|
/**
|
|
31
36
|
* @deprecated transient option soon to be removed in favor of a different design
|
|
32
37
|
*/
|
|
33
38
|
exactBoundingBox: false,
|
|
39
|
+
cornerRadius: 0,
|
|
34
40
|
};
|
|
35
41
|
|
|
36
42
|
export interface SerializedPolylineProps extends SerializedObjectProps {
|
|
37
43
|
points: XY[];
|
|
44
|
+
cornerRadius: number;
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
export class Polyline<
|
|
@@ -59,6 +66,13 @@ export class Polyline<
|
|
|
59
66
|
*/
|
|
60
67
|
declare exactBoundingBox: boolean;
|
|
61
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Corner radius for rounded corners
|
|
71
|
+
* @type Number
|
|
72
|
+
* @default 0
|
|
73
|
+
*/
|
|
74
|
+
declare cornerRadius: number;
|
|
75
|
+
|
|
62
76
|
declare private initialized: true | undefined;
|
|
63
77
|
|
|
64
78
|
static ownDefaults = polylineDefaultValues;
|
|
@@ -91,7 +105,7 @@ export class Polyline<
|
|
|
91
105
|
|
|
92
106
|
declare strokeOffset: Point;
|
|
93
107
|
|
|
94
|
-
static cacheProperties = [...cacheProperties, 'points'];
|
|
108
|
+
static cacheProperties = [...cacheProperties, 'points', 'cornerRadius'];
|
|
95
109
|
|
|
96
110
|
strokeDiff: Point;
|
|
97
111
|
|
|
@@ -312,7 +326,7 @@ export class Polyline<
|
|
|
312
326
|
K extends keyof T = never,
|
|
313
327
|
>(propertiesToInclude: K[] = []): Pick<T, K> & SProps {
|
|
314
328
|
return {
|
|
315
|
-
...super.toObject(propertiesToInclude),
|
|
329
|
+
...super.toObject(['cornerRadius', ...propertiesToInclude]),
|
|
316
330
|
points: this.points.map(({ x, y }) => ({ x, y })),
|
|
317
331
|
};
|
|
318
332
|
}
|
|
@@ -323,28 +337,42 @@ export class Polyline<
|
|
|
323
337
|
* of the instance
|
|
324
338
|
*/
|
|
325
339
|
_toSVG() {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
340
|
+
if (this.cornerRadius > 0 && this.points.length >= 3) {
|
|
341
|
+
// Generate rounded polygon/polyline as path
|
|
342
|
+
const diffX = this.pathOffset.x;
|
|
343
|
+
const diffY = this.pathOffset.y;
|
|
344
|
+
const adjustedPoints = this.points.map(point => ({
|
|
345
|
+
x: point.x - diffX,
|
|
346
|
+
y: point.y - diffY,
|
|
347
|
+
}));
|
|
348
|
+
const roundedCorners = applyCornerRadiusToPolygon(adjustedPoints, this.cornerRadius);
|
|
349
|
+
const pathData = generateRoundedPolygonPath(roundedCorners, !this.isOpen());
|
|
350
|
+
return ['<path ', 'COMMON_PARTS', `d="${pathData}" />\n`];
|
|
351
|
+
} else {
|
|
352
|
+
// Original sharp corners implementation
|
|
353
|
+
const points = [];
|
|
354
|
+
const diffX = this.pathOffset.x;
|
|
355
|
+
const diffY = this.pathOffset.y;
|
|
356
|
+
const NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS;
|
|
357
|
+
|
|
358
|
+
for (let i = 0, len = this.points.length; i < len; i++) {
|
|
359
|
+
points.push(
|
|
360
|
+
toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS),
|
|
361
|
+
',',
|
|
362
|
+
toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS),
|
|
363
|
+
' ',
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
return [
|
|
367
|
+
`<${
|
|
368
|
+
(this.constructor as typeof Polyline).type.toLowerCase() as
|
|
369
|
+
| 'polyline'
|
|
370
|
+
| 'polygon'
|
|
371
|
+
} `,
|
|
372
|
+
'COMMON_PARTS',
|
|
373
|
+
`points="${points.join('')}" />\n`,
|
|
374
|
+
];
|
|
338
375
|
}
|
|
339
|
-
return [
|
|
340
|
-
`<${
|
|
341
|
-
(this.constructor as typeof Polyline).type.toLowerCase() as
|
|
342
|
-
| 'polyline'
|
|
343
|
-
| 'polygon'
|
|
344
|
-
} `,
|
|
345
|
-
'COMMON_PARTS',
|
|
346
|
-
`points="${points.join('')}" />\n`,
|
|
347
|
-
];
|
|
348
376
|
}
|
|
349
377
|
|
|
350
378
|
/**
|
|
@@ -361,13 +389,26 @@ export class Polyline<
|
|
|
361
389
|
// NaN comes from parseFloat of a empty string in parser
|
|
362
390
|
return;
|
|
363
391
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const
|
|
368
|
-
|
|
392
|
+
|
|
393
|
+
if (this.cornerRadius > 0 && len >= 3) {
|
|
394
|
+
// Render with rounded corners
|
|
395
|
+
const adjustedPoints = this.points.map(point => ({
|
|
396
|
+
x: point.x - x,
|
|
397
|
+
y: point.y - y,
|
|
398
|
+
}));
|
|
399
|
+
const roundedCorners = applyCornerRadiusToPolygon(adjustedPoints, this.cornerRadius);
|
|
400
|
+
renderRoundedPolygon(ctx, roundedCorners, !this.isOpen());
|
|
401
|
+
} else {
|
|
402
|
+
// Original sharp corners implementation
|
|
403
|
+
ctx.beginPath();
|
|
404
|
+
ctx.moveTo(this.points[0].x - x, this.points[0].y - y);
|
|
405
|
+
for (let i = 0; i < len; i++) {
|
|
406
|
+
const point = this.points[i];
|
|
407
|
+
ctx.lineTo(point.x - x, point.y - y);
|
|
408
|
+
}
|
|
409
|
+
!this.isOpen() && ctx.closePath();
|
|
369
410
|
}
|
|
370
|
-
|
|
411
|
+
|
|
371
412
|
this._renderPaintInOrder(ctx);
|
|
372
413
|
}
|
|
373
414
|
|
package/src/shapes/Text/Text.ts
CHANGED
|
@@ -593,6 +593,8 @@ export class FabricText<
|
|
|
593
593
|
line,
|
|
594
594
|
charBound,
|
|
595
595
|
spaces;
|
|
596
|
+
const isRtl = this.direction === 'rtl';
|
|
597
|
+
|
|
596
598
|
for (let i = 0, len = this._textLines.length; i < len; i++) {
|
|
597
599
|
if (
|
|
598
600
|
this.textAlign !== JUSTIFY &&
|
|
@@ -609,15 +611,56 @@ export class FabricText<
|
|
|
609
611
|
) {
|
|
610
612
|
numberOfSpaces = spaces.length;
|
|
611
613
|
diffSpace = (this.width - currentLineWidth) / numberOfSpaces;
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
614
|
+
|
|
615
|
+
if (isRtl) {
|
|
616
|
+
// For RTL text, we need to redistribute spaces while maintaining correct visual order
|
|
617
|
+
// The key insight is that RTL text is stored in logical order but displayed in visual order
|
|
618
|
+
// We need to adjust bounds to account for the visual positioning
|
|
619
|
+
|
|
620
|
+
// First, collect all space positions
|
|
621
|
+
const spaceIndices = [];
|
|
622
|
+
for (let j = 0; j < line.length; j++) {
|
|
623
|
+
if (this._reSpaceAndTab.test(line[j])) {
|
|
624
|
+
spaceIndices.push(j);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Calculate total expansion
|
|
629
|
+
const totalExpansion = diffSpace * numberOfSpaces;
|
|
630
|
+
|
|
631
|
+
// For RTL, we need to work backwards through the visual positions
|
|
632
|
+
// but still update logical positions correctly
|
|
633
|
+
let spaceCount = 0;
|
|
634
|
+
for (let j = 0; j <= line.length; j++) {
|
|
635
|
+
charBound = this.__charBounds[i][j];
|
|
636
|
+
if (charBound) {
|
|
637
|
+
if (this._reSpaceAndTab.test(line[j])) {
|
|
638
|
+
charBound.width += diffSpace;
|
|
639
|
+
charBound.kernedWidth += diffSpace;
|
|
640
|
+
spaceCount++;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// For RTL, shift all characters to the right by the total expansion
|
|
644
|
+
// minus the expansion that comes after this character
|
|
645
|
+
const remainingSpaces = numberOfSpaces - spaceCount;
|
|
646
|
+
const shiftAmount = remainingSpaces * diffSpace;
|
|
647
|
+
charBound.left += shiftAmount;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
} else {
|
|
651
|
+
// LTR processing (original logic)
|
|
652
|
+
for (let j = 0; j <= line.length; j++) {
|
|
653
|
+
charBound = this.__charBounds[i][j];
|
|
654
|
+
if (charBound) {
|
|
655
|
+
if (this._reSpaceAndTab.test(line[j])) {
|
|
656
|
+
charBound.width += diffSpace;
|
|
657
|
+
charBound.kernedWidth += diffSpace;
|
|
658
|
+
charBound.left += accumulatedSpace;
|
|
659
|
+
accumulatedSpace += diffSpace;
|
|
660
|
+
} else {
|
|
661
|
+
charBound.left += accumulatedSpace;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
621
664
|
}
|
|
622
665
|
}
|
|
623
666
|
}
|
|
@@ -1376,7 +1419,15 @@ export class FabricText<
|
|
|
1376
1419
|
if (currentDirection !== this.direction) {
|
|
1377
1420
|
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
1378
1421
|
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
1379
|
-
|
|
1422
|
+
|
|
1423
|
+
// For justify alignments, we need to set the correct canvas text alignment
|
|
1424
|
+
// This is crucial for RTL text to render in the correct order
|
|
1425
|
+
if (isJustify) {
|
|
1426
|
+
// Justify uses LEFT alignment as a base, letting the character positioning handle justification
|
|
1427
|
+
ctx.textAlign = LEFT;
|
|
1428
|
+
} else {
|
|
1429
|
+
ctx.textAlign = isLtr ? LEFT : RIGHT;
|
|
1430
|
+
}
|
|
1380
1431
|
}
|
|
1381
1432
|
top -= (lineHeight * this._fontSizeFraction) / this.lineHeight;
|
|
1382
1433
|
if (shortCut) {
|
|
@@ -1665,14 +1716,26 @@ export class FabricText<
|
|
|
1665
1716
|
direction = this.direction,
|
|
1666
1717
|
isEndOfWrapping = this.isEndOfWrapping(lineIndex);
|
|
1667
1718
|
let leftOffset = 0;
|
|
1668
|
-
|
|
1719
|
+
|
|
1720
|
+
// Handle justify alignments (excluding last lines and wrapped line ends)
|
|
1721
|
+
const isJustifyLine =
|
|
1669
1722
|
textAlign === JUSTIFY ||
|
|
1670
1723
|
(textAlign === JUSTIFY_CENTER && !isEndOfWrapping) ||
|
|
1671
1724
|
(textAlign === JUSTIFY_RIGHT && !isEndOfWrapping) ||
|
|
1672
|
-
(textAlign === JUSTIFY_LEFT && !isEndOfWrapping)
|
|
1673
|
-
|
|
1674
|
-
|
|
1725
|
+
(textAlign === JUSTIFY_LEFT && !isEndOfWrapping);
|
|
1726
|
+
|
|
1727
|
+
if (isJustifyLine) {
|
|
1728
|
+
// Justify lines should start at the left edge for LTR and right edge for RTL
|
|
1729
|
+
// The space distribution is handled by enlargeSpaces()
|
|
1730
|
+
if (direction === 'rtl') {
|
|
1731
|
+
// For RTL justify, we need to account for the line being right-aligned
|
|
1732
|
+
return 0;
|
|
1733
|
+
} else {
|
|
1734
|
+
return 0;
|
|
1735
|
+
}
|
|
1675
1736
|
}
|
|
1737
|
+
|
|
1738
|
+
// Handle non-justify alignments
|
|
1676
1739
|
if (textAlign === CENTER) {
|
|
1677
1740
|
leftOffset = lineDiff / 2;
|
|
1678
1741
|
}
|
|
@@ -1685,6 +1748,8 @@ export class FabricText<
|
|
|
1685
1748
|
if (textAlign === JUSTIFY_RIGHT) {
|
|
1686
1749
|
leftOffset = lineDiff;
|
|
1687
1750
|
}
|
|
1751
|
+
|
|
1752
|
+
// Apply RTL adjustments for non-justify alignments
|
|
1688
1753
|
if (direction === 'rtl') {
|
|
1689
1754
|
if (
|
|
1690
1755
|
textAlign === RIGHT ||
|
package/src/shapes/Textbox.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { TClassProperties, TOptions } from '../typedefs';
|
|
|
2
2
|
import { IText } from './IText/IText';
|
|
3
3
|
import { classRegistry } from '../ClassRegistry';
|
|
4
4
|
import { createTextboxDefaultControls } from '../controls/commonControls';
|
|
5
|
-
import { JUSTIFY } from './Text/constants';
|
|
5
|
+
import { JUSTIFY, JUSTIFY_CENTER } from './Text/constants';
|
|
6
6
|
import type { TextStyleDeclaration } from './Text/StyledText';
|
|
7
7
|
import type { SerializedITextProps, ITextProps } from './IText/IText';
|
|
8
8
|
import type { ITextEvents } from './IText/ITextBehavior';
|