@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.js
CHANGED
|
@@ -71,6 +71,7 @@ __export(index_exports, {
|
|
|
71
71
|
exportPNG: () => exportPNG,
|
|
72
72
|
exportPrintArea: () => exportPrintArea,
|
|
73
73
|
exportSVG: () => exportSVG,
|
|
74
|
+
fitTextWidth: () => fitTextWidth,
|
|
74
75
|
fitToBox: () => fitToBox,
|
|
75
76
|
generateId: () => generateId,
|
|
76
77
|
isCssColor: () => isCssColor,
|
|
@@ -96,7 +97,7 @@ __export(index_exports, {
|
|
|
96
97
|
module.exports = __toCommonJS(index_exports);
|
|
97
98
|
|
|
98
99
|
// src/editor.ts
|
|
99
|
-
var
|
|
100
|
+
var import_fabric20 = require("fabric");
|
|
100
101
|
|
|
101
102
|
// src/events.ts
|
|
102
103
|
var EventEmitter = class {
|
|
@@ -1225,10 +1226,63 @@ var CropController = class {
|
|
|
1225
1226
|
var STROKE2 = "#22c55e";
|
|
1226
1227
|
|
|
1227
1228
|
// src/pattern/pattern-manager.ts
|
|
1228
|
-
var
|
|
1229
|
+
var import_fabric6 = require("fabric");
|
|
1229
1230
|
|
|
1230
1231
|
// src/pattern/tiled-pattern-object.ts
|
|
1232
|
+
var import_fabric5 = require("fabric");
|
|
1233
|
+
|
|
1234
|
+
// src/text-fit.ts
|
|
1231
1235
|
var import_fabric4 = require("fabric");
|
|
1236
|
+
var TEXT_FIT_SLACK = 0.5;
|
|
1237
|
+
var MEASURE_WIDTH = 1e5;
|
|
1238
|
+
function unwrappedWidth(text) {
|
|
1239
|
+
const authored = text.width;
|
|
1240
|
+
try {
|
|
1241
|
+
text.set({ width: MEASURE_WIDTH });
|
|
1242
|
+
text.initDimensions?.();
|
|
1243
|
+
const measured = text.calcTextWidth?.() ?? authored;
|
|
1244
|
+
return Number.isFinite(measured) && measured > 0 ? measured : authored;
|
|
1245
|
+
} finally {
|
|
1246
|
+
text.set({ width: authored });
|
|
1247
|
+
text.initDimensions?.();
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
function asText(object) {
|
|
1251
|
+
if (!object) return null;
|
|
1252
|
+
const text = object;
|
|
1253
|
+
return typeof text.text === "string" && typeof text.calcTextWidth === "function" ? text : null;
|
|
1254
|
+
}
|
|
1255
|
+
function textInk(text) {
|
|
1256
|
+
const boxWidth = Math.max(0, text.width ?? 0);
|
|
1257
|
+
const measured = text.calcTextWidth?.() ?? boxWidth;
|
|
1258
|
+
const width = Math.max(1, Math.min(boxWidth, Number.isFinite(measured) ? measured : boxWidth));
|
|
1259
|
+
const slack = (boxWidth - width) / 2;
|
|
1260
|
+
const align = text.textAlign ?? "left";
|
|
1261
|
+
if (align.includes("center")) return { width, dx: 0 };
|
|
1262
|
+
const flip = text.flipX ? -1 : 1;
|
|
1263
|
+
return { width, dx: flip * (align.includes("right") ? slack : -slack) };
|
|
1264
|
+
}
|
|
1265
|
+
function fitTextWidth(object) {
|
|
1266
|
+
const text = asText(object);
|
|
1267
|
+
if (!text || text.path) return false;
|
|
1268
|
+
const before = textInk(text);
|
|
1269
|
+
const fitted = unwrappedWidth(text) + TEXT_FIT_SLACK;
|
|
1270
|
+
if (Math.abs(fitted - text.width) < TEXT_FIT_SLACK) return false;
|
|
1271
|
+
const centre = text.getCenterPoint();
|
|
1272
|
+
text.set({ width: fitted });
|
|
1273
|
+
text.initDimensions?.();
|
|
1274
|
+
const after = textInk(text);
|
|
1275
|
+
const shift = (before.dx - after.dx) * (text.scaleX ?? 1);
|
|
1276
|
+
const radians = (text.angle ?? 0) * Math.PI / 180;
|
|
1277
|
+
const moved = new import_fabric4.Point(
|
|
1278
|
+
centre.x + shift * Math.cos(radians),
|
|
1279
|
+
centre.y + shift * Math.sin(radians)
|
|
1280
|
+
);
|
|
1281
|
+
text.setPositionByOrigin(moved, "center", "center");
|
|
1282
|
+
text.setCoords();
|
|
1283
|
+
text.dirty = true;
|
|
1284
|
+
return true;
|
|
1285
|
+
}
|
|
1232
1286
|
|
|
1233
1287
|
// src/pattern/tile-geometry.ts
|
|
1234
1288
|
var MAX_TILES_PER_AXIS = 200;
|
|
@@ -1241,13 +1295,13 @@ function computeTilePositions(config, targetW, targetH, baseW, baseH, origin) {
|
|
|
1241
1295
|
const tileH = Math.max(minTile, baseH * (1 + config.verticalSpacing / 100));
|
|
1242
1296
|
const cols = Math.ceil(span / tileW) + 2;
|
|
1243
1297
|
const rows = Math.ceil(span / tileH) + 2;
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1298
|
+
const [colFrom, colTo] = axisRange(config.horizontalLimit, Math.ceil(cols / 2));
|
|
1299
|
+
const [rowFrom, rowTo] = axisRange(config.verticalLimit, Math.ceil(rows / 2));
|
|
1246
1300
|
const shiftX = tileW * (clampOffset(config.offsetX) / 100);
|
|
1247
1301
|
const shiftY = tileH * (clampOffset(config.offsetY) / 100);
|
|
1248
1302
|
const placements = [];
|
|
1249
|
-
for (let j =
|
|
1250
|
-
for (let i =
|
|
1303
|
+
for (let j = rowFrom; j <= rowTo; j++) {
|
|
1304
|
+
for (let i = colFrom; i <= colTo; i++) {
|
|
1251
1305
|
let x = i * tileW + shiftX;
|
|
1252
1306
|
let y = j * tileH + shiftY;
|
|
1253
1307
|
if (config.mode === "brick-horizontal" && mod2(j) === 1) {
|
|
@@ -1277,6 +1331,12 @@ function drawTiles(ctx, img, config, targetW, targetH, baseW, baseH, origin, dra
|
|
|
1277
1331
|
}
|
|
1278
1332
|
ctx.restore();
|
|
1279
1333
|
}
|
|
1334
|
+
function axisRange(limit, half) {
|
|
1335
|
+
const count = Number.isFinite(limit) ? Math.floor(limit) : 0;
|
|
1336
|
+
if (!count || count <= 0) return [-half, half];
|
|
1337
|
+
const from = -Math.floor((count - 1) / 2);
|
|
1338
|
+
return [from, from + count - 1];
|
|
1339
|
+
}
|
|
1280
1340
|
function cornerRadius(origin, w, h) {
|
|
1281
1341
|
const dx = Math.max(Math.abs(origin.x), Math.abs(w - origin.x));
|
|
1282
1342
|
const dy = Math.max(Math.abs(origin.y), Math.abs(h - origin.y));
|
|
@@ -1295,7 +1355,7 @@ var MAX_SNAPSHOT_PIXELS = 16e6;
|
|
|
1295
1355
|
var MAX_SNAPSHOT_SCALE = 8;
|
|
1296
1356
|
var SNAPSHOT_SHRINK_FACTOR = 2;
|
|
1297
1357
|
var TILE_BLEED_DEVICE_PX = 2;
|
|
1298
|
-
var TiledPatternObject = class _TiledPatternObject extends
|
|
1358
|
+
var TiledPatternObject = class _TiledPatternObject extends import_fabric5.FabricObject {
|
|
1299
1359
|
static type = "TiledPattern";
|
|
1300
1360
|
/** The layer's real object. Never rendered directly (it is kept at opacity 0). */
|
|
1301
1361
|
source;
|
|
@@ -1348,7 +1408,7 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1348
1408
|
*/
|
|
1349
1409
|
syncBox() {
|
|
1350
1410
|
const { tileW, tileH } = this.baseTile();
|
|
1351
|
-
const origin = this.source.getCenterPoint();
|
|
1411
|
+
const origin = this.source.getCenterPoint().add(this.inkOffset());
|
|
1352
1412
|
const anchor = this.anchorFromOrigin(origin, tileW, tileH, this.config.angle);
|
|
1353
1413
|
this.set({
|
|
1354
1414
|
left: anchor.x,
|
|
@@ -1378,7 +1438,8 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1378
1438
|
const { tileW, tileH } = this.liveTile();
|
|
1379
1439
|
const centre = this.getCenterPoint();
|
|
1380
1440
|
const shift = this.shiftVector(tileW, tileH, this.liveAngle());
|
|
1381
|
-
|
|
1441
|
+
const ink = this.inkOffset();
|
|
1442
|
+
return new import_fabric5.Point(centre.x - shift.x - ink.x, centre.y - shift.y - ink.y);
|
|
1382
1443
|
}
|
|
1383
1444
|
_render(ctx) {
|
|
1384
1445
|
const { width, height } = this.area;
|
|
@@ -1393,8 +1454,7 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1393
1454
|
ctx.scale(1 / (this.scaleX || 1), 1 / (this.scaleY || 1));
|
|
1394
1455
|
ctx.rotate(-angle * Math.PI / 180);
|
|
1395
1456
|
ctx.translate(-centre.x, -centre.y);
|
|
1396
|
-
const
|
|
1397
|
-
const origin = { x: centre.x - shift.x, y: centre.y - shift.y };
|
|
1457
|
+
const origin = { x: centre.x, y: centre.y };
|
|
1398
1458
|
const config = { ...this.config, angle, offsetX: 0, offsetY: 0 };
|
|
1399
1459
|
drawTiles(
|
|
1400
1460
|
ctx,
|
|
@@ -1423,7 +1483,6 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1423
1483
|
if (!snapshot) return [];
|
|
1424
1484
|
const centre = this.getCenterPoint();
|
|
1425
1485
|
const angle = this.liveAngle();
|
|
1426
|
-
const shift = this.shiftVector(tileW, tileH, angle);
|
|
1427
1486
|
drawTiles(
|
|
1428
1487
|
ctx,
|
|
1429
1488
|
snapshot,
|
|
@@ -1432,7 +1491,7 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1432
1491
|
height,
|
|
1433
1492
|
tileW,
|
|
1434
1493
|
tileH,
|
|
1435
|
-
{ x: centre.x
|
|
1494
|
+
{ x: centre.x, y: centre.y },
|
|
1436
1495
|
// The fallback raster is built at 1:1, so a device pixel is a canvas unit.
|
|
1437
1496
|
this.drawSize(tileW, tileH, TILE_BLEED_DEVICE_PX)
|
|
1438
1497
|
);
|
|
@@ -1475,7 +1534,7 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1475
1534
|
return Promise.resolve(copy);
|
|
1476
1535
|
}
|
|
1477
1536
|
/**
|
|
1478
|
-
* The source's tile footprint:
|
|
1537
|
+
* The source's tile footprint: the art it paints, minus a stroke it reserves
|
|
1479
1538
|
* room for but never paints.
|
|
1480
1539
|
*
|
|
1481
1540
|
* fabric keeps `strokeWidth` inside an object's box whether or not a `stroke`
|
|
@@ -1483,11 +1542,18 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1483
1542
|
* stroke. Stepping the grid by that box puts a transparent seam between every
|
|
1484
1543
|
* pair of neighbours at zero spacing: the artwork is a pixel narrower than the
|
|
1485
1544
|
* box it is stepped by.
|
|
1545
|
+
*
|
|
1546
|
+
* Text is the same problem an order of magnitude larger — see {@link textInk}.
|
|
1486
1547
|
*/
|
|
1487
1548
|
sourceBox() {
|
|
1549
|
+
const text = asText(this.source);
|
|
1550
|
+
const paints = paintsStroke(this.source);
|
|
1488
1551
|
const rect = this.source.getBoundingRect();
|
|
1489
|
-
if (
|
|
1490
|
-
const
|
|
1552
|
+
if (paints && !text) return { width: rect.width, height: rect.height };
|
|
1553
|
+
const options = {};
|
|
1554
|
+
if (!paints) options.strokeWidth = 0;
|
|
1555
|
+
if (text) options.width = textInk(text).width;
|
|
1556
|
+
const dims = this.source._getTransformedDimensions(options);
|
|
1491
1557
|
const radians = (this.source.angle ?? 0) * Math.PI / 180;
|
|
1492
1558
|
const cos = Math.abs(Math.cos(radians));
|
|
1493
1559
|
const sin = Math.abs(Math.sin(radians));
|
|
@@ -1496,6 +1562,22 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1496
1562
|
height: dims.x * sin + dims.y * cos
|
|
1497
1563
|
};
|
|
1498
1564
|
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Vector from the source's centre to the centre of the art it paints.
|
|
1567
|
+
*
|
|
1568
|
+
* Zero for everything except text that does not fill its box: the tile has to
|
|
1569
|
+
* sit on the glyphs, or the frame the user drags frames empty space and the
|
|
1570
|
+
* grid registers off the run by half the padding.
|
|
1571
|
+
*/
|
|
1572
|
+
inkOffset() {
|
|
1573
|
+
const text = asText(this.source);
|
|
1574
|
+
if (!text) return new import_fabric5.Point(0, 0);
|
|
1575
|
+
const { dx } = textInk(text);
|
|
1576
|
+
if (!dx) return new import_fabric5.Point(0, 0);
|
|
1577
|
+
const scaled = dx * (this.source.scaleX ?? 1);
|
|
1578
|
+
const radians = (this.source.angle ?? 0) * Math.PI / 180;
|
|
1579
|
+
return new import_fabric5.Point(scaled * Math.cos(radians), scaled * Math.sin(radians));
|
|
1580
|
+
}
|
|
1499
1581
|
/** The source's on-canvas width, before the tile scale. */
|
|
1500
1582
|
baseW() {
|
|
1501
1583
|
return Math.max(1, this.sourceBox().width);
|
|
@@ -1555,11 +1637,11 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1555
1637
|
const radians = angle * Math.PI / 180;
|
|
1556
1638
|
const cos = Math.cos(radians);
|
|
1557
1639
|
const sin = Math.sin(radians);
|
|
1558
|
-
return new
|
|
1640
|
+
return new import_fabric5.Point(dx * cos - dy * sin, dx * sin + dy * cos);
|
|
1559
1641
|
}
|
|
1560
1642
|
anchorFromOrigin(origin, tileW, tileH, angle) {
|
|
1561
1643
|
const shift = this.shiftVector(tileW, tileH, angle);
|
|
1562
|
-
return new
|
|
1644
|
+
return new import_fabric5.Point(origin.x + shift.x, origin.y + shift.y);
|
|
1563
1645
|
}
|
|
1564
1646
|
/**
|
|
1565
1647
|
* Snapshot the source at (at least) `scale`, reusing the cached one while it
|
|
@@ -1572,7 +1654,15 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1572
1654
|
const source = this.source;
|
|
1573
1655
|
const opacity = source.opacity;
|
|
1574
1656
|
source.opacity = 1;
|
|
1657
|
+
const text = asText(source);
|
|
1658
|
+
const authoredWidth = text?.width;
|
|
1659
|
+
const fitted = text ? textInk(text).width + TEXT_FIT_SLACK : 0;
|
|
1660
|
+
const hug = text !== null && authoredWidth !== void 0 && fitted < authoredWidth;
|
|
1575
1661
|
try {
|
|
1662
|
+
if (hug && text) {
|
|
1663
|
+
text.set({ width: fitted });
|
|
1664
|
+
text.initDimensions?.();
|
|
1665
|
+
}
|
|
1576
1666
|
const el = source.toCanvasElement({ multiplier: wanted, enableRetinaScaling: false });
|
|
1577
1667
|
if (!el.width || !el.height) return null;
|
|
1578
1668
|
this.snapshotEl = el;
|
|
@@ -1581,6 +1671,10 @@ var TiledPatternObject = class _TiledPatternObject extends import_fabric4.Fabric
|
|
|
1581
1671
|
return this.snapshotEl;
|
|
1582
1672
|
} finally {
|
|
1583
1673
|
source.opacity = opacity;
|
|
1674
|
+
if (hug && text && authoredWidth !== void 0) {
|
|
1675
|
+
text.set({ width: authoredWidth });
|
|
1676
|
+
text.initDimensions?.();
|
|
1677
|
+
}
|
|
1584
1678
|
source.dirty = false;
|
|
1585
1679
|
}
|
|
1586
1680
|
return this.snapshotEl;
|
|
@@ -1819,7 +1913,7 @@ async function unbakeLegacyLayer(layer, state) {
|
|
|
1819
1913
|
cropY: state.original.cropY,
|
|
1820
1914
|
angle: state.original.angle
|
|
1821
1915
|
});
|
|
1822
|
-
image.clipPath = state.originalClip ? (await
|
|
1916
|
+
image.clipPath = state.originalClip ? (await import_fabric6.util.enlivenObjects([state.originalClip]))[0] : void 0;
|
|
1823
1917
|
restoreLocks(image, state.originalLocks);
|
|
1824
1918
|
image.setCoords();
|
|
1825
1919
|
}
|
|
@@ -1837,7 +1931,7 @@ function restoreLocks(obj, locks) {
|
|
|
1837
1931
|
}
|
|
1838
1932
|
|
|
1839
1933
|
// src/text-curve.ts
|
|
1840
|
-
var
|
|
1934
|
+
var import_fabric7 = require("fabric");
|
|
1841
1935
|
|
|
1842
1936
|
// src/text-curve-geometry.ts
|
|
1843
1937
|
var DEFAULT_TEXT_CURVE = {
|
|
@@ -1867,7 +1961,11 @@ function normalizeTextCurve(config) {
|
|
|
1867
1961
|
shape: config.shape ?? inferred,
|
|
1868
1962
|
arc,
|
|
1869
1963
|
wave,
|
|
1870
|
-
waveLength: clamp(
|
|
1964
|
+
waveLength: clamp(
|
|
1965
|
+
config.waveLength ?? DEFAULT_TEXT_CURVE.waveLength,
|
|
1966
|
+
MIN_WAVE_LENGTH,
|
|
1967
|
+
MAX_WAVE_LENGTH
|
|
1968
|
+
),
|
|
1871
1969
|
offset: clamp(config.offset ?? 0, -100, 100),
|
|
1872
1970
|
centerOffset: clamp(config.centerOffset ?? 0, -100, 100)
|
|
1873
1971
|
};
|
|
@@ -1957,18 +2055,55 @@ function buildCurvePathData(config, width, fontSize) {
|
|
|
1957
2055
|
}
|
|
1958
2056
|
|
|
1959
2057
|
// src/text-curve.ts
|
|
1960
|
-
var
|
|
2058
|
+
var MEASURE_WIDTH2 = 1e5;
|
|
1961
2059
|
var PATH_SLACK = 0.06;
|
|
1962
2060
|
var FALLBACK_LINE_HEIGHT = 1.16;
|
|
1963
2061
|
var patches = /* @__PURE__ */ new WeakMap();
|
|
2062
|
+
var dimensionPatches = /* @__PURE__ */ new WeakMap();
|
|
1964
2063
|
var authoredCaching = /* @__PURE__ */ new WeakMap();
|
|
2064
|
+
var GLYPH_HALF_HEIGHT = 0.7;
|
|
2065
|
+
function curvedInkSize(text) {
|
|
2066
|
+
const lineCount = text._textLines?.length ?? 0;
|
|
2067
|
+
for (let index = 0; index < lineCount; index += 1) text.getLineWidth?.(index);
|
|
2068
|
+
const lines = text.__charBounds;
|
|
2069
|
+
if (!lines?.length) return null;
|
|
2070
|
+
let halfWidth = 0;
|
|
2071
|
+
let halfHeight = 0;
|
|
2072
|
+
for (const line of lines) {
|
|
2073
|
+
for (const box of line ?? []) {
|
|
2074
|
+
const { renderLeft, renderTop } = box;
|
|
2075
|
+
if (typeof renderLeft !== "number" || typeof renderTop !== "number") continue;
|
|
2076
|
+
const halfGlyphWidth = (box.kernedWidth ?? box.width ?? 0) / 2;
|
|
2077
|
+
const halfGlyphHeight = (box.height ?? text.fontSize) * GLYPH_HALF_HEIGHT;
|
|
2078
|
+
const angle = box.angle ?? 0;
|
|
2079
|
+
const cos = Math.abs(Math.cos(angle));
|
|
2080
|
+
const sin = Math.abs(Math.sin(angle));
|
|
2081
|
+
halfWidth = Math.max(
|
|
2082
|
+
halfWidth,
|
|
2083
|
+
Math.abs(renderLeft) + halfGlyphWidth * cos + halfGlyphHeight * sin
|
|
2084
|
+
);
|
|
2085
|
+
halfHeight = Math.max(
|
|
2086
|
+
halfHeight,
|
|
2087
|
+
Math.abs(renderTop) + halfGlyphWidth * sin + halfGlyphHeight * cos
|
|
2088
|
+
);
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
if (halfWidth === 0 && halfHeight === 0) return null;
|
|
2092
|
+
return { width: halfWidth * 2, height: halfHeight * 2 };
|
|
2093
|
+
}
|
|
2094
|
+
function growBoxToInk(text) {
|
|
2095
|
+
const ink = curvedInkSize(text);
|
|
2096
|
+
if (!ink) return;
|
|
2097
|
+
if (ink.width > (text.width ?? 0)) text.width = ink.width;
|
|
2098
|
+
if (ink.height > (text.height ?? 0)) text.height = ink.height;
|
|
2099
|
+
}
|
|
1965
2100
|
function isCurvable(object) {
|
|
1966
2101
|
return !!object && typeof object.text === "string";
|
|
1967
2102
|
}
|
|
1968
2103
|
function measureText(text) {
|
|
1969
2104
|
const authored = text.width;
|
|
1970
2105
|
try {
|
|
1971
|
-
text.set({ width:
|
|
2106
|
+
text.set({ width: MEASURE_WIDTH2 });
|
|
1972
2107
|
text.initDimensions?.();
|
|
1973
2108
|
return Math.max(1, text.calcTextWidth?.() ?? text.width ?? 1);
|
|
1974
2109
|
} finally {
|
|
@@ -1985,7 +2120,7 @@ function lineHeightOf(text) {
|
|
|
1985
2120
|
return text.fontSize * (text.lineHeight ?? 1) * FALLBACK_LINE_HEIGHT;
|
|
1986
2121
|
}
|
|
1987
2122
|
function toFabricPath(curve) {
|
|
1988
|
-
return new
|
|
2123
|
+
return new import_fabric7.Path(curve.data, { visible: false, objectCaching: false });
|
|
1989
2124
|
}
|
|
1990
2125
|
var TextCurveManager = class {
|
|
1991
2126
|
constructor(canvas, layers, history, events) {
|
|
@@ -2113,6 +2248,35 @@ var TextCurveManager = class {
|
|
|
2113
2248
|
pathStartOffset: 0
|
|
2114
2249
|
});
|
|
2115
2250
|
this.patchLineMeasure(text, paths, union);
|
|
2251
|
+
this.patchDimensions(text);
|
|
2252
|
+
}
|
|
2253
|
+
/**
|
|
2254
|
+
* Re-apply {@link growBoxToInk} after every one of fabric's own dimension
|
|
2255
|
+
* passes. Typing, a font change, a style edit and a state restore all call
|
|
2256
|
+
* `initDimensions`, and each one puts the box back to the path's bounding box
|
|
2257
|
+
* — so growing it once, here, would hold only until the next keystroke.
|
|
2258
|
+
*/
|
|
2259
|
+
patchDimensions(text) {
|
|
2260
|
+
if (dimensionPatches.has(text)) return;
|
|
2261
|
+
const original = text.initDimensions;
|
|
2262
|
+
if (typeof original !== "function") return;
|
|
2263
|
+
const installed = function() {
|
|
2264
|
+
original.call(this);
|
|
2265
|
+
growBoxToInk(this);
|
|
2266
|
+
};
|
|
2267
|
+
const ownedOriginal = Object.prototype.hasOwnProperty.call(text, "initDimensions");
|
|
2268
|
+
text.initDimensions = installed;
|
|
2269
|
+
dimensionPatches.set(text, { original, installed, ownedOriginal });
|
|
2270
|
+
}
|
|
2271
|
+
/** Restore fabric's own dimension pass, if this manager replaced it. */
|
|
2272
|
+
unpatchDimensions(text) {
|
|
2273
|
+
const patch = dimensionPatches.get(text);
|
|
2274
|
+
if (!patch) return;
|
|
2275
|
+
if (text.initDimensions === patch.installed) {
|
|
2276
|
+
if (patch.ownedOriginal) text.initDimensions = patch.original;
|
|
2277
|
+
else delete text.initDimensions;
|
|
2278
|
+
}
|
|
2279
|
+
dimensionPatches.delete(text);
|
|
2116
2280
|
}
|
|
2117
2281
|
/**
|
|
2118
2282
|
* Fabric lays every line of a text object along `this.path`, from one
|
|
@@ -2164,6 +2328,7 @@ var TextCurveManager = class {
|
|
|
2164
2328
|
}
|
|
2165
2329
|
detach(text, authoredWidth) {
|
|
2166
2330
|
this.unpatchLineMeasure(text);
|
|
2331
|
+
this.unpatchDimensions(text);
|
|
2167
2332
|
const caching = authoredCaching.get(text);
|
|
2168
2333
|
if (caching !== void 0) {
|
|
2169
2334
|
text.set({ objectCaching: caching });
|
|
@@ -2175,7 +2340,7 @@ var TextCurveManager = class {
|
|
|
2175
2340
|
};
|
|
2176
2341
|
|
|
2177
2342
|
// src/mask-presets/manager.ts
|
|
2178
|
-
var
|
|
2343
|
+
var import_fabric8 = require("fabric");
|
|
2179
2344
|
|
|
2180
2345
|
// src/mask-presets/shapes.ts
|
|
2181
2346
|
var SHAPE_MASK_IDS = [
|
|
@@ -2442,13 +2607,13 @@ var MaskPresetManager = class {
|
|
|
2442
2607
|
objectCaching: false
|
|
2443
2608
|
};
|
|
2444
2609
|
if (isShapeMaskId(id)) {
|
|
2445
|
-
return new
|
|
2610
|
+
return new import_fabric8.Path(shapeMaskPathData(id), {
|
|
2446
2611
|
...shared,
|
|
2447
2612
|
scaleX: width / SHAPE_MASK_BOX,
|
|
2448
2613
|
scaleY: height / SHAPE_MASK_BOX
|
|
2449
2614
|
});
|
|
2450
2615
|
}
|
|
2451
|
-
return new
|
|
2616
|
+
return new import_fabric8.FabricImage(renderTextureMask(id), {
|
|
2452
2617
|
...shared,
|
|
2453
2618
|
scaleX: width / TEXTURE_MASK_SIZE,
|
|
2454
2619
|
scaleY: height / TEXTURE_MASK_SIZE
|
|
@@ -2457,7 +2622,7 @@ var MaskPresetManager = class {
|
|
|
2457
2622
|
};
|
|
2458
2623
|
|
|
2459
2624
|
// src/shadow.ts
|
|
2460
|
-
var
|
|
2625
|
+
var import_fabric9 = require("fabric");
|
|
2461
2626
|
|
|
2462
2627
|
// src/utils/color.ts
|
|
2463
2628
|
var CSS_COLOR = /^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\([\d.%+\-\s,/]+\)|[a-z]+)$/i;
|
|
@@ -2495,7 +2660,7 @@ function applyLayerShadow(object, config) {
|
|
|
2495
2660
|
}
|
|
2496
2661
|
const color = isCssColor(next.color) ? next.color : DEFAULT_LAYER_SHADOW.color;
|
|
2497
2662
|
object.set({
|
|
2498
|
-
shadow: new
|
|
2663
|
+
shadow: new import_fabric9.Shadow({
|
|
2499
2664
|
color,
|
|
2500
2665
|
blur: Math.max(0, next.blur),
|
|
2501
2666
|
offsetX: next.offsetX,
|
|
@@ -2609,7 +2774,7 @@ var UnitConverter = class {
|
|
|
2609
2774
|
};
|
|
2610
2775
|
|
|
2611
2776
|
// src/serialization.ts
|
|
2612
|
-
var
|
|
2777
|
+
var import_fabric10 = require("fabric");
|
|
2613
2778
|
var VERSION = "2.0.0";
|
|
2614
2779
|
function serializeEditor(editor) {
|
|
2615
2780
|
return {
|
|
@@ -2645,7 +2810,7 @@ async function deserializeEditor(editor, state) {
|
|
|
2645
2810
|
}
|
|
2646
2811
|
const staged = await Promise.all(
|
|
2647
2812
|
state.layers.map(async (serialized) => {
|
|
2648
|
-
const fabricObject = (await
|
|
2813
|
+
const fabricObject = (await import_fabric10.util.enlivenObjects([serialized.fabricObject]))[0];
|
|
2649
2814
|
if (!fabricObject) {
|
|
2650
2815
|
const source = serialized.fabricObject.src;
|
|
2651
2816
|
if (typeof source === "string" && source.startsWith("blob:")) {
|
|
@@ -2656,7 +2821,7 @@ async function deserializeEditor(editor, state) {
|
|
|
2656
2821
|
return { serialized, fabricObject };
|
|
2657
2822
|
})
|
|
2658
2823
|
);
|
|
2659
|
-
const stagedBackground = state.backgroundImage ? (await
|
|
2824
|
+
const stagedBackground = state.backgroundImage ? (await import_fabric10.util.enlivenObjects([state.backgroundImage]))[0] : null;
|
|
2660
2825
|
if (state.backgroundImage && !stagedBackground) {
|
|
2661
2826
|
const source = state.backgroundImage.src;
|
|
2662
2827
|
if (typeof source === "string" && source.startsWith("blob:")) {
|
|
@@ -2708,7 +2873,7 @@ function restoreLayer(editor, serialized, fabricObject) {
|
|
|
2708
2873
|
}
|
|
2709
2874
|
|
|
2710
2875
|
// src/export.ts
|
|
2711
|
-
var
|
|
2876
|
+
var import_fabric11 = require("fabric");
|
|
2712
2877
|
|
|
2713
2878
|
// src/displacement.ts
|
|
2714
2879
|
var CHANNEL_INDEX = {
|
|
@@ -2802,7 +2967,7 @@ async function exportPNG(canvas, options = {}) {
|
|
|
2802
2967
|
}
|
|
2803
2968
|
async function exportIsolatedPNG(source, objects, options = {}) {
|
|
2804
2969
|
const element = source.lowerCanvasEl.ownerDocument.createElement("canvas");
|
|
2805
|
-
const canvas = new
|
|
2970
|
+
const canvas = new import_fabric11.StaticCanvas(element, {
|
|
2806
2971
|
width: options.width ?? source.getWidth(),
|
|
2807
2972
|
height: options.height ?? source.getHeight(),
|
|
2808
2973
|
backgroundColor: options.backgroundColor || void 0
|
|
@@ -2832,7 +2997,7 @@ async function exportPrintArea(source, area, options = {}) {
|
|
|
2832
2997
|
throw new Error("Print area does not overlap the canvas");
|
|
2833
2998
|
}
|
|
2834
2999
|
const element = source.lowerCanvasEl.ownerDocument.createElement("canvas");
|
|
2835
|
-
const canvas = new
|
|
3000
|
+
const canvas = new import_fabric11.StaticCanvas(element, { width, height });
|
|
2836
3001
|
try {
|
|
2837
3002
|
const clones = await Promise.all(source.getObjects().map((object) => object.clone()));
|
|
2838
3003
|
if (clones.length) canvas.add(...clones);
|
|
@@ -3272,7 +3437,7 @@ var ProjectManager = class {
|
|
|
3272
3437
|
};
|
|
3273
3438
|
|
|
3274
3439
|
// src/mask.ts
|
|
3275
|
-
var
|
|
3440
|
+
var import_fabric12 = require("fabric");
|
|
3276
3441
|
var MaskRefinementError = class extends Error {
|
|
3277
3442
|
constructor(code, message, cause) {
|
|
3278
3443
|
super(message);
|
|
@@ -3304,7 +3469,7 @@ var MaskController = class {
|
|
|
3304
3469
|
throw new Error("Mask dimensions must be positive integers");
|
|
3305
3470
|
}
|
|
3306
3471
|
const backing = this.makeCanvas(width, height);
|
|
3307
|
-
const image = new
|
|
3472
|
+
const image = new import_fabric12.FabricImage(backing, {
|
|
3308
3473
|
left: 0,
|
|
3309
3474
|
top: 0,
|
|
3310
3475
|
originX: "left",
|
|
@@ -3530,10 +3695,10 @@ var MaskController = class {
|
|
|
3530
3695
|
};
|
|
3531
3696
|
|
|
3532
3697
|
// src/masks/manager.ts
|
|
3533
|
-
var
|
|
3698
|
+
var import_fabric19 = require("fabric");
|
|
3534
3699
|
|
|
3535
3700
|
// src/masks/compose.ts
|
|
3536
|
-
var
|
|
3701
|
+
var import_fabric13 = require("fabric");
|
|
3537
3702
|
var MODE_OPERATION = {
|
|
3538
3703
|
add: "source-over",
|
|
3539
3704
|
subtract: "destination-out",
|
|
@@ -3543,7 +3708,7 @@ function neutralize(child) {
|
|
|
3543
3708
|
child.set({ opacity: 0, globalCompositeOperation: "source-over" });
|
|
3544
3709
|
}
|
|
3545
3710
|
function baseRect(box) {
|
|
3546
|
-
return new
|
|
3711
|
+
return new import_fabric13.Rect({
|
|
3547
3712
|
left: box.left,
|
|
3548
3713
|
top: box.top,
|
|
3549
3714
|
width: Math.max(1, box.width),
|
|
@@ -3570,7 +3735,7 @@ function composeMaskGroup(children, entries, options) {
|
|
|
3570
3735
|
});
|
|
3571
3736
|
const first = entries.find((entry) => entry.visible);
|
|
3572
3737
|
const withBase = first && first.mode !== "add" ? [baseRect(options.box), ...children] : [...children];
|
|
3573
|
-
return new
|
|
3738
|
+
return new import_fabric13.Group(withBase, {
|
|
3574
3739
|
absolutePositioned: options.absolute,
|
|
3575
3740
|
// Cached, so the children's compositing operations resolve against each
|
|
3576
3741
|
// other instead of against the page underneath the mask.
|
|
@@ -3584,15 +3749,15 @@ function needsAbsoluteSpace(entries) {
|
|
|
3584
3749
|
}
|
|
3585
3750
|
|
|
3586
3751
|
// src/masks/edit.ts
|
|
3587
|
-
var
|
|
3752
|
+
var import_fabric15 = require("fabric");
|
|
3588
3753
|
|
|
3589
3754
|
// src/masks/space.ts
|
|
3590
|
-
var
|
|
3755
|
+
var import_fabric14 = require("fabric");
|
|
3591
3756
|
function matrixOf(object) {
|
|
3592
3757
|
return object.calcTransformMatrix();
|
|
3593
3758
|
}
|
|
3594
3759
|
function applyMatrix(object, matrix) {
|
|
3595
|
-
const decomposed =
|
|
3760
|
+
const decomposed = import_fabric14.util.qrDecompose(matrix);
|
|
3596
3761
|
object.set({
|
|
3597
3762
|
flipX: false,
|
|
3598
3763
|
flipY: false,
|
|
@@ -3609,19 +3774,19 @@ function applyMatrix(object, matrix) {
|
|
|
3609
3774
|
object.setCoords();
|
|
3610
3775
|
}
|
|
3611
3776
|
function toCanvasSpace(object, host) {
|
|
3612
|
-
applyMatrix(object,
|
|
3777
|
+
applyMatrix(object, import_fabric14.util.multiplyTransformMatrices(matrixOf(host), matrixOf(object)));
|
|
3613
3778
|
}
|
|
3614
3779
|
function toHostSpace(object, host) {
|
|
3615
3780
|
applyMatrix(
|
|
3616
3781
|
object,
|
|
3617
|
-
|
|
3782
|
+
import_fabric14.util.multiplyTransformMatrices(import_fabric14.util.invertTransform(matrixOf(host)), matrixOf(object))
|
|
3618
3783
|
);
|
|
3619
3784
|
}
|
|
3620
3785
|
function relativeMatrix(object, host) {
|
|
3621
|
-
return
|
|
3786
|
+
return import_fabric14.util.multiplyTransformMatrices(import_fabric14.util.invertTransform(matrixOf(host)), matrixOf(object));
|
|
3622
3787
|
}
|
|
3623
3788
|
function applyRelativeMatrix(object, host, rel) {
|
|
3624
|
-
applyMatrix(object,
|
|
3789
|
+
applyMatrix(object, import_fabric14.util.multiplyTransformMatrices(matrixOf(host), rel));
|
|
3625
3790
|
}
|
|
3626
3791
|
function asObject(clip) {
|
|
3627
3792
|
return clip;
|
|
@@ -3734,8 +3899,8 @@ var MaskEditController = class {
|
|
|
3734
3899
|
if (!this.handle || !this.child || !this.group) return;
|
|
3735
3900
|
applyMatrix(
|
|
3736
3901
|
this.child,
|
|
3737
|
-
|
|
3738
|
-
|
|
3902
|
+
import_fabric15.util.multiplyTransformMatrices(
|
|
3903
|
+
import_fabric15.util.invertTransform(matrixOf(this.group)),
|
|
3739
3904
|
matrixOf(this.handle)
|
|
3740
3905
|
)
|
|
3741
3906
|
);
|
|
@@ -3746,15 +3911,15 @@ var MaskEditController = class {
|
|
|
3746
3911
|
};
|
|
3747
3912
|
|
|
3748
3913
|
// src/masks/store.ts
|
|
3749
|
-
var
|
|
3914
|
+
var import_fabric18 = require("fabric");
|
|
3750
3915
|
|
|
3751
3916
|
// src/masks/host.ts
|
|
3752
|
-
var
|
|
3917
|
+
var import_fabric16 = require("fabric");
|
|
3753
3918
|
function findCanvasHost(layers) {
|
|
3754
3919
|
return layers.getAll().find((layer) => layer.meta.canvasMask);
|
|
3755
3920
|
}
|
|
3756
3921
|
function createCanvasHost(canvas, layers) {
|
|
3757
|
-
const rect = new
|
|
3922
|
+
const rect = new import_fabric16.Rect({
|
|
3758
3923
|
left: 0,
|
|
3759
3924
|
top: 0,
|
|
3760
3925
|
width: canvas.getWidth(),
|
|
@@ -3803,9 +3968,9 @@ function hostBoxOf(canvas, host, absolute) {
|
|
|
3803
3968
|
}
|
|
3804
3969
|
|
|
3805
3970
|
// src/masks/install.ts
|
|
3806
|
-
var
|
|
3971
|
+
var import_fabric17 = require("fabric");
|
|
3807
3972
|
function convertSpace(host, sources, absolute) {
|
|
3808
|
-
const wasAbsolute = host.clipPath instanceof
|
|
3973
|
+
const wasAbsolute = host.clipPath instanceof import_fabric17.Group ? host.clipPath.absolutePositioned : absolute;
|
|
3809
3974
|
if (absolute === wasAbsolute) return;
|
|
3810
3975
|
for (const source of sources) {
|
|
3811
3976
|
if (absolute) toCanvasSpace(source, host);
|
|
@@ -3897,7 +4062,7 @@ var MaskStackStore = class {
|
|
|
3897
4062
|
const clip = host.clipPath;
|
|
3898
4063
|
if (!clip) return [];
|
|
3899
4064
|
const entries = this.list(target);
|
|
3900
|
-
if (entries.length === 0 || !(clip instanceof
|
|
4065
|
+
if (entries.length === 0 || !(clip instanceof import_fabric18.Group)) return [asObject(clip)];
|
|
3901
4066
|
const children = unwrapGroup(clip);
|
|
3902
4067
|
const extra = children.length - entries.length;
|
|
3903
4068
|
return extra > 0 ? children.slice(extra) : children;
|
|
@@ -3956,8 +4121,8 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
3956
4121
|
onLayersChanged = () => this.pin();
|
|
3957
4122
|
// Selecting a layer means the user has moved on from the mask they had open;
|
|
3958
4123
|
// leaving both selected would show mask controls for an unrelated layer.
|
|
3959
|
-
onLayerSelected = () => {
|
|
3960
|
-
if (this.selected) this.select(null, null);
|
|
4124
|
+
onLayerSelected = ({ layerId }) => {
|
|
4125
|
+
if (layerId && this.selected) this.select(null, null);
|
|
3961
4126
|
};
|
|
3962
4127
|
onObjectModified = (event) => {
|
|
3963
4128
|
const object = event.target;
|
|
@@ -3997,7 +4162,7 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
3997
4162
|
if (index === -1) return false;
|
|
3998
4163
|
this.endEdit(false);
|
|
3999
4164
|
this.commit(target, host, [...entries], this.unwrap(target, host), false, true);
|
|
4000
|
-
const group = host.clipPath instanceof
|
|
4165
|
+
const group = host.clipPath instanceof import_fabric19.Group ? host.clipPath : null;
|
|
4001
4166
|
if (!group) return false;
|
|
4002
4167
|
const children = group.getObjects();
|
|
4003
4168
|
const child = children[children.length - entries.length + index];
|
|
@@ -4017,6 +4182,7 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
4017
4182
|
}
|
|
4018
4183
|
select(target, maskId) {
|
|
4019
4184
|
this.selected = target && maskId ? { target, maskId } : null;
|
|
4185
|
+
if (this.selected) this.layers.select(null);
|
|
4020
4186
|
this.events.emit("mask:selected", { target, maskId: this.selected ? maskId : null });
|
|
4021
4187
|
}
|
|
4022
4188
|
// ─── Mutations ───────────────────────────────────────
|
|
@@ -4177,6 +4343,9 @@ var LayerMaskManager = class extends MaskStackStore {
|
|
|
4177
4343
|
if (resolved === layerId) return null;
|
|
4178
4344
|
const object = layer.fabricObject;
|
|
4179
4345
|
if (!object.fill && object.type !== "image") object.set({ fill: "#000000" });
|
|
4346
|
+
const stackHost = this.host(resolved);
|
|
4347
|
+
const absolute = resolved === CANVAS_MASK_TARGET || needsAbsoluteSpace(this.list(resolved));
|
|
4348
|
+
if (!absolute && stackHost) toHostSpace(object, stackHost);
|
|
4180
4349
|
this.history.beginTransaction();
|
|
4181
4350
|
try {
|
|
4182
4351
|
if (this.canvas.getActiveObject() === object) this.canvas.discardActiveObject();
|
|
@@ -4303,7 +4472,7 @@ var CanvasEditor = class {
|
|
|
4303
4472
|
const widthPx = this.units.toPixels(config.width);
|
|
4304
4473
|
const heightPx = this.units.toPixels(config.height);
|
|
4305
4474
|
this.designBackground = config.backgroundColor ?? "#ffffff";
|
|
4306
|
-
this.canvas = new
|
|
4475
|
+
this.canvas = new import_fabric20.Canvas(canvasElement, {
|
|
4307
4476
|
width: widthPx,
|
|
4308
4477
|
height: heightPx,
|
|
4309
4478
|
backgroundColor: this.designBackground,
|
|
@@ -4337,7 +4506,7 @@ var CanvasEditor = class {
|
|
|
4337
4506
|
// ─── Layer Operations ────────────────────────────────
|
|
4338
4507
|
async addImage(url, options) {
|
|
4339
4508
|
try {
|
|
4340
|
-
const img = await
|
|
4509
|
+
const img = await import_fabric20.FabricImage.fromURL(
|
|
4341
4510
|
url,
|
|
4342
4511
|
{},
|
|
4343
4512
|
{ originX: "left", originY: "top", ...options }
|
|
@@ -4363,7 +4532,7 @@ var CanvasEditor = class {
|
|
|
4363
4532
|
if (this.crop.activeLayerId() === layerId) this.crop.cancel();
|
|
4364
4533
|
const previous = layer.fabricObject;
|
|
4365
4534
|
try {
|
|
4366
|
-
const replacement = await
|
|
4535
|
+
const replacement = await import_fabric20.FabricImage.fromURL(url, {}, { originX: "left", originY: "top" });
|
|
4367
4536
|
replacement.set({
|
|
4368
4537
|
left: previous.left,
|
|
4369
4538
|
top: previous.top,
|
|
@@ -4392,7 +4561,7 @@ var CanvasEditor = class {
|
|
|
4392
4561
|
}
|
|
4393
4562
|
}
|
|
4394
4563
|
addText(text, options) {
|
|
4395
|
-
const textbox = new
|
|
4564
|
+
const textbox = new import_fabric20.Textbox(text, {
|
|
4396
4565
|
fontSize: 32,
|
|
4397
4566
|
fontFamily: "Arial",
|
|
4398
4567
|
fill: "#000000",
|
|
@@ -4523,10 +4692,10 @@ var CanvasEditor = class {
|
|
|
4523
4692
|
const next = { ...previous, ...adjustments };
|
|
4524
4693
|
const clampAdjustment = (value, min = -1) => clamp(value ?? 0, min, 1);
|
|
4525
4694
|
image.filters = [
|
|
4526
|
-
new
|
|
4527
|
-
new
|
|
4528
|
-
new
|
|
4529
|
-
new
|
|
4695
|
+
new import_fabric20.filters.Brightness({ brightness: clampAdjustment(next.brightness) }),
|
|
4696
|
+
new import_fabric20.filters.Contrast({ contrast: clampAdjustment(next.contrast) }),
|
|
4697
|
+
new import_fabric20.filters.Saturation({ saturation: clampAdjustment(next.saturation) }),
|
|
4698
|
+
new import_fabric20.filters.Blur({ blur: clampAdjustment(next.blur, 0) })
|
|
4530
4699
|
];
|
|
4531
4700
|
layer.meta.imageAdjustments = next;
|
|
4532
4701
|
image.applyFilters();
|
|
@@ -4567,7 +4736,7 @@ var CanvasEditor = class {
|
|
|
4567
4736
|
this.layers.detach(layer.id);
|
|
4568
4737
|
}
|
|
4569
4738
|
}
|
|
4570
|
-
const group = new
|
|
4739
|
+
const group = new import_fabric20.Group(objects);
|
|
4571
4740
|
const grouped = this.layers.add("group", group, name);
|
|
4572
4741
|
this.layers.adoptChildren(grouped, children);
|
|
4573
4742
|
this.layers.reorder(grouped.id, insertIndex);
|
|
@@ -4629,7 +4798,7 @@ var CanvasEditor = class {
|
|
|
4629
4798
|
const layer = this.layers.get(id);
|
|
4630
4799
|
if (!layer) throw new Error(`Layer not found: ${id}`);
|
|
4631
4800
|
try {
|
|
4632
|
-
if (options.resolution === "source" && layer.fabricObject instanceof
|
|
4801
|
+
if (options.resolution === "source" && layer.fabricObject instanceof import_fabric20.FabricImage) {
|
|
4633
4802
|
const image = await layer.fabricObject.clone();
|
|
4634
4803
|
image.set({
|
|
4635
4804
|
left: 0,
|
|
@@ -4905,7 +5074,7 @@ var CanvasEditor = class {
|
|
|
4905
5074
|
return;
|
|
4906
5075
|
}
|
|
4907
5076
|
try {
|
|
4908
|
-
const image = await
|
|
5077
|
+
const image = await import_fabric20.FabricImage.fromURL(
|
|
4909
5078
|
url,
|
|
4910
5079
|
{ crossOrigin: options.crossOrigin ?? null, signal: options.signal },
|
|
4911
5080
|
{ originX: "left", originY: "top" }
|
|
@@ -5238,11 +5407,15 @@ var DEFAULT_PATTERN_CONFIG = {
|
|
|
5238
5407
|
horizontalSpacing: 0,
|
|
5239
5408
|
verticalSpacing: 0,
|
|
5240
5409
|
angle: 0,
|
|
5241
|
-
|
|
5410
|
+
// Half a tile: the offset only bites in the brick modes, and a brick course
|
|
5411
|
+
// that is not half-shifted is just a grid with extra steps.
|
|
5412
|
+
horizontalOffset: 50,
|
|
5242
5413
|
offsetX: 0,
|
|
5243
5414
|
offsetY: 0,
|
|
5244
5415
|
rotationStepH: 0,
|
|
5245
|
-
rotationStepV: 0
|
|
5416
|
+
rotationStepV: 0,
|
|
5417
|
+
horizontalLimit: 0,
|
|
5418
|
+
verticalLimit: 0
|
|
5246
5419
|
};
|
|
5247
5420
|
|
|
5248
5421
|
// src/presets.ts
|
|
@@ -5348,6 +5521,7 @@ var AnnotationOverlay = class {
|
|
|
5348
5521
|
exportPNG,
|
|
5349
5522
|
exportPrintArea,
|
|
5350
5523
|
exportSVG,
|
|
5524
|
+
fitTextWidth,
|
|
5351
5525
|
fitToBox,
|
|
5352
5526
|
generateId,
|
|
5353
5527
|
isCssColor,
|