@overtone-art/canvas-editor-core 0.6.2 → 0.6.4
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.d.mts +45 -4
- package/dist/index.d.ts +45 -4
- package/dist/index.global.js +53 -53
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +246 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +196 -23
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/{types-LM7pOkkj.d.mts → types-DSu2jbiV.d.mts} +8 -0
- package/dist/{types-LM7pOkkj.d.ts → types-DSu2jbiV.d.ts} +8 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1143,7 +1143,60 @@ var STROKE2 = "#22c55e";
|
|
|
1143
1143
|
import { util } from "fabric";
|
|
1144
1144
|
|
|
1145
1145
|
// src/pattern/tiled-pattern-object.ts
|
|
1146
|
-
import { FabricObject, Point } from "fabric";
|
|
1146
|
+
import { FabricObject, Point as Point2 } from "fabric";
|
|
1147
|
+
|
|
1148
|
+
// src/text-fit.ts
|
|
1149
|
+
import { Point } from "fabric";
|
|
1150
|
+
var TEXT_FIT_SLACK = 0.5;
|
|
1151
|
+
var MEASURE_WIDTH = 1e5;
|
|
1152
|
+
function unwrappedWidth(text) {
|
|
1153
|
+
const authored = text.width;
|
|
1154
|
+
try {
|
|
1155
|
+
text.set({ width: MEASURE_WIDTH });
|
|
1156
|
+
text.initDimensions?.();
|
|
1157
|
+
const measured = text.calcTextWidth?.() ?? authored;
|
|
1158
|
+
return Number.isFinite(measured) && measured > 0 ? measured : authored;
|
|
1159
|
+
} finally {
|
|
1160
|
+
text.set({ width: authored });
|
|
1161
|
+
text.initDimensions?.();
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
function asText(object) {
|
|
1165
|
+
if (!object) return null;
|
|
1166
|
+
const text = object;
|
|
1167
|
+
return typeof text.text === "string" && typeof text.calcTextWidth === "function" ? text : null;
|
|
1168
|
+
}
|
|
1169
|
+
function textInk(text) {
|
|
1170
|
+
const boxWidth = Math.max(0, text.width ?? 0);
|
|
1171
|
+
const measured = text.calcTextWidth?.() ?? boxWidth;
|
|
1172
|
+
const width = Math.max(1, Math.min(boxWidth, Number.isFinite(measured) ? measured : boxWidth));
|
|
1173
|
+
const slack = (boxWidth - width) / 2;
|
|
1174
|
+
const align = text.textAlign ?? "left";
|
|
1175
|
+
if (align.includes("center")) return { width, dx: 0 };
|
|
1176
|
+
const flip = text.flipX ? -1 : 1;
|
|
1177
|
+
return { width, dx: flip * (align.includes("right") ? slack : -slack) };
|
|
1178
|
+
}
|
|
1179
|
+
function fitTextWidth(object) {
|
|
1180
|
+
const text = asText(object);
|
|
1181
|
+
if (!text || text.path) return false;
|
|
1182
|
+
const before = textInk(text);
|
|
1183
|
+
const fitted = unwrappedWidth(text) + TEXT_FIT_SLACK;
|
|
1184
|
+
if (Math.abs(fitted - text.width) < TEXT_FIT_SLACK) return false;
|
|
1185
|
+
const centre = text.getCenterPoint();
|
|
1186
|
+
text.set({ width: fitted });
|
|
1187
|
+
text.initDimensions?.();
|
|
1188
|
+
const after = textInk(text);
|
|
1189
|
+
const shift = (before.dx - after.dx) * (text.scaleX ?? 1);
|
|
1190
|
+
const radians = (text.angle ?? 0) * Math.PI / 180;
|
|
1191
|
+
const moved = new Point(
|
|
1192
|
+
centre.x + shift * Math.cos(radians),
|
|
1193
|
+
centre.y + shift * Math.sin(radians)
|
|
1194
|
+
);
|
|
1195
|
+
text.setPositionByOrigin(moved, "center", "center");
|
|
1196
|
+
text.setCoords();
|
|
1197
|
+
text.dirty = true;
|
|
1198
|
+
return true;
|
|
1199
|
+
}
|
|
1147
1200
|
|
|
1148
1201
|
// src/pattern/tile-geometry.ts
|
|
1149
1202
|
var MAX_TILES_PER_AXIS = 200;
|
|
@@ -1156,13 +1209,13 @@ function computeTilePositions(config, targetW, targetH, baseW, baseH, origin) {
|
|
|
1156
1209
|
const tileH = Math.max(minTile, baseH * (1 + config.verticalSpacing / 100));
|
|
1157
1210
|
const cols = Math.ceil(span / tileW) + 2;
|
|
1158
1211
|
const rows = Math.ceil(span / tileH) + 2;
|
|
1159
|
-
const
|
|
1160
|
-
const
|
|
1212
|
+
const [colFrom, colTo] = axisRange(config.horizontalLimit, Math.ceil(cols / 2));
|
|
1213
|
+
const [rowFrom, rowTo] = axisRange(config.verticalLimit, Math.ceil(rows / 2));
|
|
1161
1214
|
const shiftX = tileW * (clampOffset(config.offsetX) / 100);
|
|
1162
1215
|
const shiftY = tileH * (clampOffset(config.offsetY) / 100);
|
|
1163
1216
|
const placements = [];
|
|
1164
|
-
for (let j =
|
|
1165
|
-
for (let i =
|
|
1217
|
+
for (let j = rowFrom; j <= rowTo; j++) {
|
|
1218
|
+
for (let i = colFrom; i <= colTo; i++) {
|
|
1166
1219
|
let x = i * tileW + shiftX;
|
|
1167
1220
|
let y = j * tileH + shiftY;
|
|
1168
1221
|
if (config.mode === "brick-horizontal" && mod2(j) === 1) {
|
|
@@ -1192,6 +1245,12 @@ function drawTiles(ctx, img, config, targetW, targetH, baseW, baseH, origin, dra
|
|
|
1192
1245
|
}
|
|
1193
1246
|
ctx.restore();
|
|
1194
1247
|
}
|
|
1248
|
+
function axisRange(limit, half) {
|
|
1249
|
+
const count = Number.isFinite(limit) ? Math.floor(limit) : 0;
|
|
1250
|
+
if (!count || count <= 0) return [-half, half];
|
|
1251
|
+
const from = -Math.floor((count - 1) / 2);
|
|
1252
|
+
return [from, from + count - 1];
|
|
1253
|
+
}
|
|
1195
1254
|
function cornerRadius(origin, w, h) {
|
|
1196
1255
|
const dx = Math.max(Math.abs(origin.x), Math.abs(w - origin.x));
|
|
1197
1256
|
const dy = Math.max(Math.abs(origin.y), Math.abs(h - origin.y));
|
|
@@ -1263,7 +1322,7 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1263
1322
|
*/
|
|
1264
1323
|
syncBox() {
|
|
1265
1324
|
const { tileW, tileH } = this.baseTile();
|
|
1266
|
-
const origin = this.source.getCenterPoint();
|
|
1325
|
+
const origin = this.source.getCenterPoint().add(this.inkOffset());
|
|
1267
1326
|
const anchor = this.anchorFromOrigin(origin, tileW, tileH, this.config.angle);
|
|
1268
1327
|
this.set({
|
|
1269
1328
|
left: anchor.x,
|
|
@@ -1293,7 +1352,8 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1293
1352
|
const { tileW, tileH } = this.liveTile();
|
|
1294
1353
|
const centre = this.getCenterPoint();
|
|
1295
1354
|
const shift = this.shiftVector(tileW, tileH, this.liveAngle());
|
|
1296
|
-
|
|
1355
|
+
const ink = this.inkOffset();
|
|
1356
|
+
return new Point2(centre.x - shift.x - ink.x, centre.y - shift.y - ink.y);
|
|
1297
1357
|
}
|
|
1298
1358
|
_render(ctx) {
|
|
1299
1359
|
const { width, height } = this.area;
|
|
@@ -1308,8 +1368,7 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1308
1368
|
ctx.scale(1 / (this.scaleX || 1), 1 / (this.scaleY || 1));
|
|
1309
1369
|
ctx.rotate(-angle * Math.PI / 180);
|
|
1310
1370
|
ctx.translate(-centre.x, -centre.y);
|
|
1311
|
-
const
|
|
1312
|
-
const origin = { x: centre.x - shift.x, y: centre.y - shift.y };
|
|
1371
|
+
const origin = { x: centre.x, y: centre.y };
|
|
1313
1372
|
const config = { ...this.config, angle, offsetX: 0, offsetY: 0 };
|
|
1314
1373
|
drawTiles(
|
|
1315
1374
|
ctx,
|
|
@@ -1338,7 +1397,6 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1338
1397
|
if (!snapshot) return [];
|
|
1339
1398
|
const centre = this.getCenterPoint();
|
|
1340
1399
|
const angle = this.liveAngle();
|
|
1341
|
-
const shift = this.shiftVector(tileW, tileH, angle);
|
|
1342
1400
|
drawTiles(
|
|
1343
1401
|
ctx,
|
|
1344
1402
|
snapshot,
|
|
@@ -1347,7 +1405,7 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1347
1405
|
height,
|
|
1348
1406
|
tileW,
|
|
1349
1407
|
tileH,
|
|
1350
|
-
{ x: centre.x
|
|
1408
|
+
{ x: centre.x, y: centre.y },
|
|
1351
1409
|
// The fallback raster is built at 1:1, so a device pixel is a canvas unit.
|
|
1352
1410
|
this.drawSize(tileW, tileH, TILE_BLEED_DEVICE_PX)
|
|
1353
1411
|
);
|
|
@@ -1390,7 +1448,7 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1390
1448
|
return Promise.resolve(copy);
|
|
1391
1449
|
}
|
|
1392
1450
|
/**
|
|
1393
|
-
* The source's tile footprint:
|
|
1451
|
+
* The source's tile footprint: the art it paints, minus a stroke it reserves
|
|
1394
1452
|
* room for but never paints.
|
|
1395
1453
|
*
|
|
1396
1454
|
* fabric keeps `strokeWidth` inside an object's box whether or not a `stroke`
|
|
@@ -1398,11 +1456,18 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1398
1456
|
* stroke. Stepping the grid by that box puts a transparent seam between every
|
|
1399
1457
|
* pair of neighbours at zero spacing: the artwork is a pixel narrower than the
|
|
1400
1458
|
* box it is stepped by.
|
|
1459
|
+
*
|
|
1460
|
+
* Text is the same problem an order of magnitude larger — see {@link textInk}.
|
|
1401
1461
|
*/
|
|
1402
1462
|
sourceBox() {
|
|
1463
|
+
const text = asText(this.source);
|
|
1464
|
+
const paints = paintsStroke(this.source);
|
|
1403
1465
|
const rect = this.source.getBoundingRect();
|
|
1404
|
-
if (
|
|
1405
|
-
const
|
|
1466
|
+
if (paints && !text) return { width: rect.width, height: rect.height };
|
|
1467
|
+
const options = {};
|
|
1468
|
+
if (!paints) options.strokeWidth = 0;
|
|
1469
|
+
if (text) options.width = textInk(text).width;
|
|
1470
|
+
const dims = this.source._getTransformedDimensions(options);
|
|
1406
1471
|
const radians = (this.source.angle ?? 0) * Math.PI / 180;
|
|
1407
1472
|
const cos = Math.abs(Math.cos(radians));
|
|
1408
1473
|
const sin = Math.abs(Math.sin(radians));
|
|
@@ -1411,6 +1476,22 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1411
1476
|
height: dims.x * sin + dims.y * cos
|
|
1412
1477
|
};
|
|
1413
1478
|
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Vector from the source's centre to the centre of the art it paints.
|
|
1481
|
+
*
|
|
1482
|
+
* Zero for everything except text that does not fill its box: the tile has to
|
|
1483
|
+
* sit on the glyphs, or the frame the user drags frames empty space and the
|
|
1484
|
+
* grid registers off the run by half the padding.
|
|
1485
|
+
*/
|
|
1486
|
+
inkOffset() {
|
|
1487
|
+
const text = asText(this.source);
|
|
1488
|
+
if (!text) return new Point2(0, 0);
|
|
1489
|
+
const { dx } = textInk(text);
|
|
1490
|
+
if (!dx) return new Point2(0, 0);
|
|
1491
|
+
const scaled = dx * (this.source.scaleX ?? 1);
|
|
1492
|
+
const radians = (this.source.angle ?? 0) * Math.PI / 180;
|
|
1493
|
+
return new Point2(scaled * Math.cos(radians), scaled * Math.sin(radians));
|
|
1494
|
+
}
|
|
1414
1495
|
/** The source's on-canvas width, before the tile scale. */
|
|
1415
1496
|
baseW() {
|
|
1416
1497
|
return Math.max(1, this.sourceBox().width);
|
|
@@ -1470,11 +1551,11 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1470
1551
|
const radians = angle * Math.PI / 180;
|
|
1471
1552
|
const cos = Math.cos(radians);
|
|
1472
1553
|
const sin = Math.sin(radians);
|
|
1473
|
-
return new
|
|
1554
|
+
return new Point2(dx * cos - dy * sin, dx * sin + dy * cos);
|
|
1474
1555
|
}
|
|
1475
1556
|
anchorFromOrigin(origin, tileW, tileH, angle) {
|
|
1476
1557
|
const shift = this.shiftVector(tileW, tileH, angle);
|
|
1477
|
-
return new
|
|
1558
|
+
return new Point2(origin.x + shift.x, origin.y + shift.y);
|
|
1478
1559
|
}
|
|
1479
1560
|
/**
|
|
1480
1561
|
* Snapshot the source at (at least) `scale`, reusing the cached one while it
|
|
@@ -1487,7 +1568,15 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1487
1568
|
const source = this.source;
|
|
1488
1569
|
const opacity = source.opacity;
|
|
1489
1570
|
source.opacity = 1;
|
|
1571
|
+
const text = asText(source);
|
|
1572
|
+
const authoredWidth = text?.width;
|
|
1573
|
+
const fitted = text ? textInk(text).width + TEXT_FIT_SLACK : 0;
|
|
1574
|
+
const hug = text !== null && authoredWidth !== void 0 && fitted < authoredWidth;
|
|
1490
1575
|
try {
|
|
1576
|
+
if (hug && text) {
|
|
1577
|
+
text.set({ width: fitted });
|
|
1578
|
+
text.initDimensions?.();
|
|
1579
|
+
}
|
|
1491
1580
|
const el = source.toCanvasElement({ multiplier: wanted, enableRetinaScaling: false });
|
|
1492
1581
|
if (!el.width || !el.height) return null;
|
|
1493
1582
|
this.snapshotEl = el;
|
|
@@ -1496,6 +1585,10 @@ var TiledPatternObject = class _TiledPatternObject extends FabricObject {
|
|
|
1496
1585
|
return this.snapshotEl;
|
|
1497
1586
|
} finally {
|
|
1498
1587
|
source.opacity = opacity;
|
|
1588
|
+
if (hug && text && authoredWidth !== void 0) {
|
|
1589
|
+
text.set({ width: authoredWidth });
|
|
1590
|
+
text.initDimensions?.();
|
|
1591
|
+
}
|
|
1499
1592
|
source.dirty = false;
|
|
1500
1593
|
}
|
|
1501
1594
|
return this.snapshotEl;
|
|
@@ -1782,7 +1875,11 @@ function normalizeTextCurve(config) {
|
|
|
1782
1875
|
shape: config.shape ?? inferred,
|
|
1783
1876
|
arc,
|
|
1784
1877
|
wave,
|
|
1785
|
-
waveLength: clamp(
|
|
1878
|
+
waveLength: clamp(
|
|
1879
|
+
config.waveLength ?? DEFAULT_TEXT_CURVE.waveLength,
|
|
1880
|
+
MIN_WAVE_LENGTH,
|
|
1881
|
+
MAX_WAVE_LENGTH
|
|
1882
|
+
),
|
|
1786
1883
|
offset: clamp(config.offset ?? 0, -100, 100),
|
|
1787
1884
|
centerOffset: clamp(config.centerOffset ?? 0, -100, 100)
|
|
1788
1885
|
};
|
|
@@ -1872,18 +1969,55 @@ function buildCurvePathData(config, width, fontSize) {
|
|
|
1872
1969
|
}
|
|
1873
1970
|
|
|
1874
1971
|
// src/text-curve.ts
|
|
1875
|
-
var
|
|
1972
|
+
var MEASURE_WIDTH2 = 1e5;
|
|
1876
1973
|
var PATH_SLACK = 0.06;
|
|
1877
1974
|
var FALLBACK_LINE_HEIGHT = 1.16;
|
|
1878
1975
|
var patches = /* @__PURE__ */ new WeakMap();
|
|
1976
|
+
var dimensionPatches = /* @__PURE__ */ new WeakMap();
|
|
1879
1977
|
var authoredCaching = /* @__PURE__ */ new WeakMap();
|
|
1978
|
+
var GLYPH_HALF_HEIGHT = 0.7;
|
|
1979
|
+
function curvedInkSize(text) {
|
|
1980
|
+
const lineCount = text._textLines?.length ?? 0;
|
|
1981
|
+
for (let index = 0; index < lineCount; index += 1) text.getLineWidth?.(index);
|
|
1982
|
+
const lines = text.__charBounds;
|
|
1983
|
+
if (!lines?.length) return null;
|
|
1984
|
+
let halfWidth = 0;
|
|
1985
|
+
let halfHeight = 0;
|
|
1986
|
+
for (const line of lines) {
|
|
1987
|
+
for (const box of line ?? []) {
|
|
1988
|
+
const { renderLeft, renderTop } = box;
|
|
1989
|
+
if (typeof renderLeft !== "number" || typeof renderTop !== "number") continue;
|
|
1990
|
+
const halfGlyphWidth = (box.kernedWidth ?? box.width ?? 0) / 2;
|
|
1991
|
+
const halfGlyphHeight = (box.height ?? text.fontSize) * GLYPH_HALF_HEIGHT;
|
|
1992
|
+
const angle = box.angle ?? 0;
|
|
1993
|
+
const cos = Math.abs(Math.cos(angle));
|
|
1994
|
+
const sin = Math.abs(Math.sin(angle));
|
|
1995
|
+
halfWidth = Math.max(
|
|
1996
|
+
halfWidth,
|
|
1997
|
+
Math.abs(renderLeft) + halfGlyphWidth * cos + halfGlyphHeight * sin
|
|
1998
|
+
);
|
|
1999
|
+
halfHeight = Math.max(
|
|
2000
|
+
halfHeight,
|
|
2001
|
+
Math.abs(renderTop) + halfGlyphWidth * sin + halfGlyphHeight * cos
|
|
2002
|
+
);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
if (halfWidth === 0 && halfHeight === 0) return null;
|
|
2006
|
+
return { width: halfWidth * 2, height: halfHeight * 2 };
|
|
2007
|
+
}
|
|
2008
|
+
function growBoxToInk(text) {
|
|
2009
|
+
const ink = curvedInkSize(text);
|
|
2010
|
+
if (!ink) return;
|
|
2011
|
+
if (ink.width > (text.width ?? 0)) text.width = ink.width;
|
|
2012
|
+
if (ink.height > (text.height ?? 0)) text.height = ink.height;
|
|
2013
|
+
}
|
|
1880
2014
|
function isCurvable(object) {
|
|
1881
2015
|
return !!object && typeof object.text === "string";
|
|
1882
2016
|
}
|
|
1883
2017
|
function measureText(text) {
|
|
1884
2018
|
const authored = text.width;
|
|
1885
2019
|
try {
|
|
1886
|
-
text.set({ width:
|
|
2020
|
+
text.set({ width: MEASURE_WIDTH2 });
|
|
1887
2021
|
text.initDimensions?.();
|
|
1888
2022
|
return Math.max(1, text.calcTextWidth?.() ?? text.width ?? 1);
|
|
1889
2023
|
} finally {
|
|
@@ -2028,6 +2162,35 @@ var TextCurveManager = class {
|
|
|
2028
2162
|
pathStartOffset: 0
|
|
2029
2163
|
});
|
|
2030
2164
|
this.patchLineMeasure(text, paths, union);
|
|
2165
|
+
this.patchDimensions(text);
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Re-apply {@link growBoxToInk} after every one of fabric's own dimension
|
|
2169
|
+
* passes. Typing, a font change, a style edit and a state restore all call
|
|
2170
|
+
* `initDimensions`, and each one puts the box back to the path's bounding box
|
|
2171
|
+
* — so growing it once, here, would hold only until the next keystroke.
|
|
2172
|
+
*/
|
|
2173
|
+
patchDimensions(text) {
|
|
2174
|
+
if (dimensionPatches.has(text)) return;
|
|
2175
|
+
const original = text.initDimensions;
|
|
2176
|
+
if (typeof original !== "function") return;
|
|
2177
|
+
const installed = function() {
|
|
2178
|
+
original.call(this);
|
|
2179
|
+
growBoxToInk(this);
|
|
2180
|
+
};
|
|
2181
|
+
const ownedOriginal = Object.prototype.hasOwnProperty.call(text, "initDimensions");
|
|
2182
|
+
text.initDimensions = installed;
|
|
2183
|
+
dimensionPatches.set(text, { original, installed, ownedOriginal });
|
|
2184
|
+
}
|
|
2185
|
+
/** Restore fabric's own dimension pass, if this manager replaced it. */
|
|
2186
|
+
unpatchDimensions(text) {
|
|
2187
|
+
const patch = dimensionPatches.get(text);
|
|
2188
|
+
if (!patch) return;
|
|
2189
|
+
if (text.initDimensions === patch.installed) {
|
|
2190
|
+
if (patch.ownedOriginal) text.initDimensions = patch.original;
|
|
2191
|
+
else delete text.initDimensions;
|
|
2192
|
+
}
|
|
2193
|
+
dimensionPatches.delete(text);
|
|
2031
2194
|
}
|
|
2032
2195
|
/**
|
|
2033
2196
|
* Fabric lays every line of a text object along `this.path`, from one
|
|
@@ -2079,6 +2242,7 @@ var TextCurveManager = class {
|
|
|
2079
2242
|
}
|
|
2080
2243
|
detach(text, authoredWidth) {
|
|
2081
2244
|
this.unpatchLineMeasure(text);
|
|
2245
|
+
this.unpatchDimensions(text);
|
|
2082
2246
|
const caching = authoredCaching.get(text);
|
|
2083
2247
|
if (caching !== void 0) {
|
|
2084
2248
|
text.set({ objectCaching: caching });
|
|
@@ -3620,8 +3784,8 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
3620
3784
|
onLayersChanged = () => this.pin();
|
|
3621
3785
|
// Selecting a layer means the user has moved on from the mask they had open;
|
|
3622
3786
|
// leaving both selected would show mask controls for an unrelated layer.
|
|
3623
|
-
onLayerSelected = () => {
|
|
3624
|
-
if (this.selected) this.select(null, null);
|
|
3787
|
+
onLayerSelected = ({ layerId }) => {
|
|
3788
|
+
if (layerId && this.selected) this.select(null, null);
|
|
3625
3789
|
};
|
|
3626
3790
|
onObjectModified = (event) => {
|
|
3627
3791
|
const object = event.target;
|
|
@@ -3681,6 +3845,7 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
3681
3845
|
}
|
|
3682
3846
|
select(target, maskId) {
|
|
3683
3847
|
this.selected = target && maskId ? { target, maskId } : null;
|
|
3848
|
+
if (this.selected) this.layers.select(null);
|
|
3684
3849
|
this.events.emit("mask:selected", { target, maskId: this.selected ? maskId : null });
|
|
3685
3850
|
}
|
|
3686
3851
|
// ─── Mutations ───────────────────────────────────────
|
|
@@ -3841,6 +4006,9 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
3841
4006
|
if (resolved === layerId) return null;
|
|
3842
4007
|
const object = layer.fabricObject;
|
|
3843
4008
|
if (!object.fill && object.type !== "image") object.set({ fill: "#000000" });
|
|
4009
|
+
const stackHost = this.host(resolved);
|
|
4010
|
+
const absolute = resolved === CANVAS_MASK_TARGET || needsAbsoluteSpace(this.list(resolved));
|
|
4011
|
+
if (!absolute && stackHost) toHostSpace(object, stackHost);
|
|
3844
4012
|
this.history.beginTransaction();
|
|
3845
4013
|
try {
|
|
3846
4014
|
if (this.canvas.getActiveObject() === object) this.canvas.discardActiveObject();
|
|
@@ -4902,11 +5070,15 @@ var DEFAULT_PATTERN_CONFIG = {
|
|
|
4902
5070
|
horizontalSpacing: 0,
|
|
4903
5071
|
verticalSpacing: 0,
|
|
4904
5072
|
angle: 0,
|
|
4905
|
-
|
|
5073
|
+
// Half a tile: the offset only bites in the brick modes, and a brick course
|
|
5074
|
+
// that is not half-shifted is just a grid with extra steps.
|
|
5075
|
+
horizontalOffset: 50,
|
|
4906
5076
|
offsetX: 0,
|
|
4907
5077
|
offsetY: 0,
|
|
4908
5078
|
rotationStepH: 0,
|
|
4909
|
-
rotationStepV: 0
|
|
5079
|
+
rotationStepV: 0,
|
|
5080
|
+
horizontalLimit: 0,
|
|
5081
|
+
verticalLimit: 0
|
|
4910
5082
|
};
|
|
4911
5083
|
|
|
4912
5084
|
// src/presets.ts
|
|
@@ -5011,6 +5183,7 @@ export {
|
|
|
5011
5183
|
exportPNG,
|
|
5012
5184
|
exportPrintArea,
|
|
5013
5185
|
exportSVG,
|
|
5186
|
+
fitTextWidth,
|
|
5014
5187
|
fitToBox,
|
|
5015
5188
|
generateId,
|
|
5016
5189
|
isCssColor,
|