label-printer 0.10.0 → 0.12.0
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 +80 -32
- package/dist/index.d.ts +80 -32
- package/dist/index.js +390 -86
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +390 -86
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -271,6 +271,19 @@ function dotToPoint(dots, dpi) {
|
|
|
271
271
|
const inch = dots / dpi;
|
|
272
272
|
return Math.round(inch * pointsPerInch);
|
|
273
273
|
}
|
|
274
|
+
function inToDot(inches, dpi, round = false) {
|
|
275
|
+
const res = inches * dpi;
|
|
276
|
+
if (round) return Math.round(res);
|
|
277
|
+
else return res;
|
|
278
|
+
}
|
|
279
|
+
function mmToDot(mm, dpi, round = false) {
|
|
280
|
+
const res = mm / 25.4 * dpi;
|
|
281
|
+
if (round) return Math.round(res);
|
|
282
|
+
else return res;
|
|
283
|
+
}
|
|
284
|
+
function unitToDot(value, dpi, unitSystem, round = false) {
|
|
285
|
+
return unitSystem === "imperial" ? inToDot(value, dpi, round) : mmToDot(value, dpi, round);
|
|
286
|
+
}
|
|
274
287
|
|
|
275
288
|
// src/helpers/ImageDataParser.ts
|
|
276
289
|
function parsePNG(buffer2) {
|
|
@@ -521,7 +534,6 @@ var ImageProcessor = class {
|
|
|
521
534
|
*/
|
|
522
535
|
static getImageDataNode(image2, _target) {
|
|
523
536
|
return __async(this, null, function* () {
|
|
524
|
-
console.log("Processing image in Node.js environment");
|
|
525
537
|
if (image2 instanceof Blob) {
|
|
526
538
|
throw new Error("Blob input not supported in Node.js environment. Use file path or data URL instead.");
|
|
527
539
|
}
|
|
@@ -690,7 +702,6 @@ var ImageProcessor = class {
|
|
|
690
702
|
*/
|
|
691
703
|
static parse(buffer2, extension) {
|
|
692
704
|
const normalizedExtension = extension.startsWith(".") ? extension.slice(1) : extension;
|
|
693
|
-
console.log(`Parsing image with extension: ${normalizedExtension}`);
|
|
694
705
|
if (normalizedExtension === "png") {
|
|
695
706
|
return parsePNG(buffer2);
|
|
696
707
|
} else if (normalizedExtension === "jpeg" || normalizedExtension === "jpg") {
|
|
@@ -1104,6 +1115,54 @@ ${widthBits} ${height}
|
|
|
1104
1115
|
fs.writeFileSync(filePath, bytes);
|
|
1105
1116
|
});
|
|
1106
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Rotate a BW bitmap by 90, 180 or 270 degrees clockwise.
|
|
1120
|
+
* The bitmap uses 0=black, 1=white with MSB-first packing.
|
|
1121
|
+
*/
|
|
1122
|
+
static rotateBWBitmap(bitmap2, rotation) {
|
|
1123
|
+
const srcWidthBytes = bitmap2.width;
|
|
1124
|
+
const srcWidthBits = srcWidthBytes * 8;
|
|
1125
|
+
const srcHeight = bitmap2.height;
|
|
1126
|
+
const src = bitmap2.bytes;
|
|
1127
|
+
const getBit = (col, row) => {
|
|
1128
|
+
const byteIndex = row * srcWidthBytes + (col >> 3);
|
|
1129
|
+
const bitIndex = 7 - (col & 7);
|
|
1130
|
+
return src[byteIndex] >> bitIndex & 1;
|
|
1131
|
+
};
|
|
1132
|
+
let dstWidthBits;
|
|
1133
|
+
let dstHeight;
|
|
1134
|
+
let getNewPixel;
|
|
1135
|
+
if (rotation === 90) {
|
|
1136
|
+
dstWidthBits = srcHeight;
|
|
1137
|
+
dstHeight = srcWidthBits;
|
|
1138
|
+
getNewPixel = (col, row) => getBit(srcWidthBits - 1 - row, col);
|
|
1139
|
+
} else if (rotation === 270) {
|
|
1140
|
+
dstWidthBits = srcHeight;
|
|
1141
|
+
dstHeight = srcWidthBits;
|
|
1142
|
+
getNewPixel = (col, row) => getBit(row, srcHeight - 1 - col);
|
|
1143
|
+
} else {
|
|
1144
|
+
dstWidthBits = srcWidthBits;
|
|
1145
|
+
dstHeight = srcHeight;
|
|
1146
|
+
getNewPixel = (col, row) => getBit(srcWidthBits - 1 - col, srcHeight - 1 - row);
|
|
1147
|
+
}
|
|
1148
|
+
const dstPad = dstWidthBits % 8 === 0 ? 0 : 8 - dstWidthBits % 8;
|
|
1149
|
+
const dstWidthBitsPadded = dstWidthBits + dstPad;
|
|
1150
|
+
const dstWidthBytes = dstWidthBitsPadded / 8;
|
|
1151
|
+
const dst = new Uint8Array(dstWidthBytes * dstHeight).fill(255);
|
|
1152
|
+
for (let row = 0; row < dstHeight; row++) {
|
|
1153
|
+
for (let col = 0; col < dstWidthBits; col++) {
|
|
1154
|
+
const bit = getNewPixel(col, row);
|
|
1155
|
+
const byteIndex = row * dstWidthBytes + (col >> 3);
|
|
1156
|
+
const mask = 1 << 7 - (col & 7);
|
|
1157
|
+
if (bit === 1) {
|
|
1158
|
+
dst[byteIndex] |= mask;
|
|
1159
|
+
} else {
|
|
1160
|
+
dst[byteIndex] &= ~mask & 255;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
return { width: dstWidthBytes, height: dstHeight, bytes: dst };
|
|
1165
|
+
}
|
|
1107
1166
|
static dilateOnce(bitmap2) {
|
|
1108
1167
|
const widthBytes = bitmap2.width;
|
|
1109
1168
|
const widthBits = widthBytes * 8;
|
|
@@ -1205,20 +1264,6 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
|
|
|
1205
1264
|
}
|
|
1206
1265
|
};
|
|
1207
1266
|
|
|
1208
|
-
// src/commands/tspl/types.ts
|
|
1209
|
-
var alignmentToNumber = (alignment) => {
|
|
1210
|
-
switch (alignment) {
|
|
1211
|
-
case void 0:
|
|
1212
|
-
return 0;
|
|
1213
|
-
case "left":
|
|
1214
|
-
return 1;
|
|
1215
|
-
case "center":
|
|
1216
|
-
return 2;
|
|
1217
|
-
case "right":
|
|
1218
|
-
return 3;
|
|
1219
|
-
}
|
|
1220
|
-
};
|
|
1221
|
-
|
|
1222
1267
|
// src/commands/tspl/commands/basic/TSPLTextCommand.ts
|
|
1223
1268
|
var TSPLTextCommand = class extends TSPLVisualCommand {
|
|
1224
1269
|
constructor(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment) {
|
|
@@ -1509,9 +1554,9 @@ var TSPLCommandGenerator = class _TSPLCommandGenerator {
|
|
|
1509
1554
|
print(sets, copiesPerSet) {
|
|
1510
1555
|
return new TSPLPrintCommand(sets, copiesPerSet);
|
|
1511
1556
|
}
|
|
1512
|
-
text(content, x, y, font, size) {
|
|
1557
|
+
text(content, x, y, font, size, rotation) {
|
|
1513
1558
|
const fontName = font == "default" ? "0" : font;
|
|
1514
|
-
return new TSPLTextCommand(content, x, y, fontName, 0, size, size, "left");
|
|
1559
|
+
return new TSPLTextCommand(content, x, y, fontName, rotation != null ? rotation : 0, size, size, "left");
|
|
1515
1560
|
}
|
|
1516
1561
|
upload(name, data) {
|
|
1517
1562
|
return new TSPLDownload(name, data);
|
|
@@ -1538,10 +1583,10 @@ var TSPLCommandGenerator = class _TSPLCommandGenerator {
|
|
|
1538
1583
|
image(image2, x, y, mode) {
|
|
1539
1584
|
return new TSPLBitmapCommand(image2, x, y, mode);
|
|
1540
1585
|
}
|
|
1541
|
-
qrCode(content, width, x, y) {
|
|
1586
|
+
qrCode(content, width, x, y, rotation) {
|
|
1542
1587
|
const cellCount = this.cellCount(content);
|
|
1543
1588
|
const cellWidth = Math.round(width / cellCount);
|
|
1544
|
-
return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M");
|
|
1589
|
+
return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M", rotation != null ? rotation : 0);
|
|
1545
1590
|
}
|
|
1546
1591
|
barCode(content, x, y, type, height, rotation, humanReadable, alignment, barWidth = 2) {
|
|
1547
1592
|
const { narrow, wide } = _TSPLCommandGenerator.narrowWideFor(type, barWidth);
|
|
@@ -1591,6 +1636,20 @@ var TSPLCommandGenerator = class _TSPLCommandGenerator {
|
|
|
1591
1636
|
};
|
|
1592
1637
|
var TSPLCommandGenerator_default = new TSPLCommandGenerator();
|
|
1593
1638
|
|
|
1639
|
+
// src/commands/tspl/types.ts
|
|
1640
|
+
var alignmentToNumber = (alignment) => {
|
|
1641
|
+
switch (alignment) {
|
|
1642
|
+
case void 0:
|
|
1643
|
+
return 0;
|
|
1644
|
+
case "left":
|
|
1645
|
+
return 1;
|
|
1646
|
+
case "center":
|
|
1647
|
+
return 2;
|
|
1648
|
+
case "right":
|
|
1649
|
+
return 3;
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
|
|
1594
1653
|
// src/printers/index.ts
|
|
1595
1654
|
var printers_exports = {};
|
|
1596
1655
|
__export(printers_exports, {
|
|
@@ -2418,7 +2477,7 @@ var Printable = class {
|
|
|
2418
2477
|
/**
|
|
2419
2478
|
* Generates printable command for the given printer. Can be used to obtain a command for fields supported by the package then customizing it before printing
|
|
2420
2479
|
* @param printer Printer to generate the command. Important because the command is printer language specific
|
|
2421
|
-
* @returns A promise for a command. Most commands are
|
|
2480
|
+
* @returns A promise for a command. Most commands are synchronous but some may require to access async resources
|
|
2422
2481
|
*/
|
|
2423
2482
|
commandForPrinter(printer, config) {
|
|
2424
2483
|
return __async(this, null, function* () {
|
|
@@ -2437,8 +2496,105 @@ var Printable = class {
|
|
|
2437
2496
|
}
|
|
2438
2497
|
};
|
|
2439
2498
|
|
|
2499
|
+
// src/labels/types.ts
|
|
2500
|
+
var rotationForOrientation = (orientation) => {
|
|
2501
|
+
switch (orientation) {
|
|
2502
|
+
case "normal":
|
|
2503
|
+
return 0;
|
|
2504
|
+
case "left":
|
|
2505
|
+
return 90;
|
|
2506
|
+
case "upside-down":
|
|
2507
|
+
return 180;
|
|
2508
|
+
case "right":
|
|
2509
|
+
return 270;
|
|
2510
|
+
}
|
|
2511
|
+
};
|
|
2512
|
+
|
|
2440
2513
|
// src/labels/Label.ts
|
|
2441
2514
|
var fontkit = __toESM(require("fontkit"));
|
|
2515
|
+
|
|
2516
|
+
// src/labels/fields/superClasses/LabelField.ts
|
|
2517
|
+
var LabelField = class extends Printable {
|
|
2518
|
+
};
|
|
2519
|
+
|
|
2520
|
+
// src/labels/fields/superClasses/RotatableLabelField.ts
|
|
2521
|
+
var RotatableLabelField = class extends LabelField {
|
|
2522
|
+
constructor() {
|
|
2523
|
+
super(...arguments);
|
|
2524
|
+
this.rotation = 0;
|
|
2525
|
+
}
|
|
2526
|
+
setRotation(rotation) {
|
|
2527
|
+
this.rotation = rotation;
|
|
2528
|
+
}
|
|
2529
|
+
getRotation() {
|
|
2530
|
+
return this.rotation;
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
|
|
2534
|
+
// src/labels/RotatableContainer.ts
|
|
2535
|
+
var RotatableContainer = class extends RotatableLabelField {
|
|
2536
|
+
/**
|
|
2537
|
+
* @param size Size in dots
|
|
2538
|
+
*/
|
|
2539
|
+
constructor(size) {
|
|
2540
|
+
super();
|
|
2541
|
+
this.fields = [];
|
|
2542
|
+
this.size = size;
|
|
2543
|
+
}
|
|
2544
|
+
/**
|
|
2545
|
+
* Place fields in the container
|
|
2546
|
+
* @param fields
|
|
2547
|
+
*/
|
|
2548
|
+
add(...fields) {
|
|
2549
|
+
this.fields.push(...fields);
|
|
2550
|
+
}
|
|
2551
|
+
commandForLanguage(language, config) {
|
|
2552
|
+
return __async(this, null, function* () {
|
|
2553
|
+
const commandList = yield Promise.all(this.fields.map((field) => this.rotationAdjustedCommand(field, language, config)));
|
|
2554
|
+
return this.commandGeneratorFor(language).commandGroup(commandList);
|
|
2555
|
+
});
|
|
2556
|
+
}
|
|
2557
|
+
rotationAdjustedCommand(field, language, config) {
|
|
2558
|
+
return __async(this, null, function* () {
|
|
2559
|
+
let originalRotation = void 0;
|
|
2560
|
+
let originalPosition = void 0;
|
|
2561
|
+
if (field.hasOwnProperty("rotation")) {
|
|
2562
|
+
const rotatableField = field;
|
|
2563
|
+
originalRotation = rotatableField.getRotation();
|
|
2564
|
+
rotatableField.setRotation((originalRotation + this.rotation) % 360);
|
|
2565
|
+
}
|
|
2566
|
+
if (typeof field.getPosition === "function" && typeof field.setPosition === "function") {
|
|
2567
|
+
const positionedField = field;
|
|
2568
|
+
originalPosition = positionedField.getPosition();
|
|
2569
|
+
positionedField.setPosition(this.adjustPosition(originalPosition));
|
|
2570
|
+
}
|
|
2571
|
+
const command = yield field.commandForLanguage(language, config);
|
|
2572
|
+
if (originalRotation !== void 0) {
|
|
2573
|
+
const rotatableField = field;
|
|
2574
|
+
rotatableField.setRotation(originalRotation);
|
|
2575
|
+
}
|
|
2576
|
+
if (originalPosition !== void 0) {
|
|
2577
|
+
const positionedField = field;
|
|
2578
|
+
positionedField.setPosition(originalPosition);
|
|
2579
|
+
}
|
|
2580
|
+
return command;
|
|
2581
|
+
});
|
|
2582
|
+
}
|
|
2583
|
+
adjustPosition(position) {
|
|
2584
|
+
switch (this.rotation) {
|
|
2585
|
+
case 90:
|
|
2586
|
+
return { x: this.size.height - position.y, y: position.x };
|
|
2587
|
+
case 180:
|
|
2588
|
+
return { x: this.size.width - position.x, y: this.size.height - position.y };
|
|
2589
|
+
case 270:
|
|
2590
|
+
return { x: position.y, y: this.size.width - position.x };
|
|
2591
|
+
default:
|
|
2592
|
+
return position;
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
};
|
|
2596
|
+
|
|
2597
|
+
// src/labels/Label.ts
|
|
2442
2598
|
var DEFAULT_FONT_WEIGHT = 400;
|
|
2443
2599
|
var DEFAULT_FONT_STYLE = "normal";
|
|
2444
2600
|
var FONT_PREFIX = "f";
|
|
@@ -2447,10 +2603,7 @@ var Label = class extends Printable {
|
|
|
2447
2603
|
super();
|
|
2448
2604
|
this.fonts = {};
|
|
2449
2605
|
this.density = 8;
|
|
2450
|
-
|
|
2451
|
-
* List of fields on the label
|
|
2452
|
-
*/
|
|
2453
|
-
this.fields = [];
|
|
2606
|
+
this.orientation = "normal";
|
|
2454
2607
|
this.fontCounter = 0;
|
|
2455
2608
|
this._textWidthCorrectionFactor = 0.935;
|
|
2456
2609
|
this.width = width;
|
|
@@ -2458,6 +2611,9 @@ var Label = class extends Printable {
|
|
|
2458
2611
|
this.unitSystem = dimensionUnit;
|
|
2459
2612
|
this.dpi = dpi;
|
|
2460
2613
|
this.density = density;
|
|
2614
|
+
const widthInDots = unitToDot(width, dpi, dimensionUnit);
|
|
2615
|
+
const heightInDots = unitToDot(height, dpi, dimensionUnit);
|
|
2616
|
+
this.container = new RotatableContainer({ width: widthInDots, height: heightInDots });
|
|
2461
2617
|
}
|
|
2462
2618
|
/**
|
|
2463
2619
|
* Configuration used when generating commands
|
|
@@ -2488,11 +2644,17 @@ var Label = class extends Printable {
|
|
|
2488
2644
|
setTextWidthCorrectionFactor(factor) {
|
|
2489
2645
|
this._textWidthCorrectionFactor = factor;
|
|
2490
2646
|
}
|
|
2647
|
+
/**
|
|
2648
|
+
* Change the orientation the label is printed in. This will rotate all fields in the container
|
|
2649
|
+
* @param orientation
|
|
2650
|
+
*/
|
|
2651
|
+
setOrientation(orientation) {
|
|
2652
|
+
this.orientation = orientation;
|
|
2653
|
+
this.container.setRotation(rotationForOrientation(orientation));
|
|
2654
|
+
}
|
|
2491
2655
|
commandForLanguage(language, config) {
|
|
2492
2656
|
return __async(this, null, function* () {
|
|
2493
|
-
|
|
2494
|
-
const commandList = yield Promise.all(this.fields.map((field) => field.commandForLanguage(language, configuration)));
|
|
2495
|
-
return this.commandGeneratorFor(language).commandGroup(commandList);
|
|
2657
|
+
return yield this.container.commandForLanguage(language, config);
|
|
2496
2658
|
});
|
|
2497
2659
|
}
|
|
2498
2660
|
/**
|
|
@@ -2500,7 +2662,7 @@ var Label = class extends Printable {
|
|
|
2500
2662
|
* @param fields
|
|
2501
2663
|
*/
|
|
2502
2664
|
add(...fields) {
|
|
2503
|
-
this.
|
|
2665
|
+
this.container.add(...fields);
|
|
2504
2666
|
}
|
|
2505
2667
|
/**
|
|
2506
2668
|
* Register a font to be used. Use the name provided in components to use the font.
|
|
@@ -2566,11 +2728,17 @@ var Label = class extends Printable {
|
|
|
2566
2728
|
*/
|
|
2567
2729
|
fullCommand(language, gap, direction, mirror = false, gapOffset = 0, generator) {
|
|
2568
2730
|
return __async(this, null, function* () {
|
|
2731
|
+
let finalDimations;
|
|
2732
|
+
if (this.orientation == "normal" || this.orientation == "upside-down") {
|
|
2733
|
+
finalDimations = { width: this.width, height: this.height };
|
|
2734
|
+
} else {
|
|
2735
|
+
finalDimations = { width: this.height, height: this.width };
|
|
2736
|
+
}
|
|
2569
2737
|
const commands = [
|
|
2570
2738
|
this.fontUploadCommands(generator),
|
|
2571
2739
|
generator.setUp(
|
|
2572
|
-
|
|
2573
|
-
|
|
2740
|
+
finalDimations.width,
|
|
2741
|
+
finalDimations.height,
|
|
2574
2742
|
gap,
|
|
2575
2743
|
gapOffset,
|
|
2576
2744
|
direction,
|
|
@@ -2601,10 +2769,10 @@ var Label = class extends Printable {
|
|
|
2601
2769
|
const family = this.fonts[font.name];
|
|
2602
2770
|
if (!family) return null;
|
|
2603
2771
|
const style = (_a = font.style) != null ? _a : DEFAULT_FONT_STYLE;
|
|
2604
|
-
const
|
|
2772
|
+
const weight = (_b = font.weight) != null ? _b : DEFAULT_FONT_WEIGHT;
|
|
2605
2773
|
const fontKeys = Object.keys(family.fonts);
|
|
2606
2774
|
const exactMatch = fontKeys.find(
|
|
2607
|
-
(key) => family.fonts[key].style == style && family.fonts[key].weight ==
|
|
2775
|
+
(key) => family.fonts[key].style == style && family.fonts[key].weight == weight
|
|
2608
2776
|
);
|
|
2609
2777
|
if (exactMatch) {
|
|
2610
2778
|
return family.fonts[exactMatch];
|
|
@@ -2614,7 +2782,7 @@ var Label = class extends Printable {
|
|
|
2614
2782
|
let weigthDiff = 99999999;
|
|
2615
2783
|
let selectedKey = "";
|
|
2616
2784
|
sameStyleKeys.forEach((key) => {
|
|
2617
|
-
const diff = Math.abs(
|
|
2785
|
+
const diff = Math.abs(weight - family.fonts[key].weight);
|
|
2618
2786
|
if (diff < weigthDiff) {
|
|
2619
2787
|
weigthDiff = diff;
|
|
2620
2788
|
selectedKey = key;
|
|
@@ -2642,10 +2810,6 @@ var Label = class extends Printable {
|
|
|
2642
2810
|
}
|
|
2643
2811
|
};
|
|
2644
2812
|
|
|
2645
|
-
// src/labels/fields/LabelField.ts
|
|
2646
|
-
var LabelField = class extends Printable {
|
|
2647
|
-
};
|
|
2648
|
-
|
|
2649
2813
|
// src/labels/fields/Line.ts
|
|
2650
2814
|
var Line = class extends LabelField {
|
|
2651
2815
|
/**
|
|
@@ -2674,7 +2838,7 @@ var UNDERLINE_TAG = "u";
|
|
|
2674
2838
|
var STRIKE_TAG = ["s", "del", "strike"];
|
|
2675
2839
|
var PARAGRAPH_TAG = "p";
|
|
2676
2840
|
var BREAK_TAG = "br";
|
|
2677
|
-
var Text = class extends
|
|
2841
|
+
var Text = class extends RotatableLabelField {
|
|
2678
2842
|
constructor(content, x, y, formatted = true) {
|
|
2679
2843
|
super();
|
|
2680
2844
|
this.font = { name: "default", size: 10 };
|
|
@@ -2704,6 +2868,13 @@ var Text = class extends LabelField {
|
|
|
2704
2868
|
}
|
|
2705
2869
|
return false;
|
|
2706
2870
|
}
|
|
2871
|
+
setPosition(position) {
|
|
2872
|
+
this.x = position.x;
|
|
2873
|
+
this.y = position.y;
|
|
2874
|
+
}
|
|
2875
|
+
getPosition() {
|
|
2876
|
+
return { x: this.x, y: this.y };
|
|
2877
|
+
}
|
|
2707
2878
|
/**
|
|
2708
2879
|
* Sets the field to single line
|
|
2709
2880
|
* @param width Max width of the text. Leave it undefined to allow the field to grow
|
|
@@ -2724,13 +2895,81 @@ var Text = class extends LabelField {
|
|
|
2724
2895
|
this.height = height;
|
|
2725
2896
|
}
|
|
2726
2897
|
/**
|
|
2727
|
-
* Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used
|
|
2898
|
+
* Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used
|
|
2728
2899
|
* Note: The font name either has to be a built in font on your printer or a font
|
|
2729
2900
|
* that is registered on the label using 'registerFont'.
|
|
2730
2901
|
*/
|
|
2731
2902
|
setFont(font) {
|
|
2732
2903
|
this.font = font;
|
|
2733
2904
|
}
|
|
2905
|
+
// --- Rotation-aware position helpers ---
|
|
2906
|
+
/** Advance cursor by `amount` along the character direction */
|
|
2907
|
+
advanceChar(x, y, amount) {
|
|
2908
|
+
switch (this.rotation) {
|
|
2909
|
+
case 0:
|
|
2910
|
+
return { x: x + amount, y };
|
|
2911
|
+
case 90:
|
|
2912
|
+
return { x, y: y + amount };
|
|
2913
|
+
// 90° CW: chars go downward
|
|
2914
|
+
case 180:
|
|
2915
|
+
return { x: x - amount, y };
|
|
2916
|
+
case 270:
|
|
2917
|
+
return { x, y: y - amount };
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
/** Advance to the next line (reset char axis, advance in line direction) */
|
|
2921
|
+
advanceLine(x, y, lineHeight) {
|
|
2922
|
+
switch (this.rotation) {
|
|
2923
|
+
case 0:
|
|
2924
|
+
return { x: this.x, y: y + lineHeight };
|
|
2925
|
+
case 90:
|
|
2926
|
+
return { x: x - lineHeight, y: this.y };
|
|
2927
|
+
// 90° CW: lines stack leftward (-x)
|
|
2928
|
+
case 180:
|
|
2929
|
+
return { x: this.x, y: y - lineHeight };
|
|
2930
|
+
case 270:
|
|
2931
|
+
return { x: x + lineHeight, y: this.y };
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
/** How far into the current line the cursor is (for width constraint calc) */
|
|
2935
|
+
charOffset(x, y) {
|
|
2936
|
+
switch (this.rotation) {
|
|
2937
|
+
case 0:
|
|
2938
|
+
return x - this.x;
|
|
2939
|
+
case 90:
|
|
2940
|
+
return y - this.y;
|
|
2941
|
+
// 90° CW: char axis is +y
|
|
2942
|
+
case 180:
|
|
2943
|
+
return this.x - x;
|
|
2944
|
+
case 270:
|
|
2945
|
+
return this.y - y;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
/** How many lines deep we are (for height constraint calc) */
|
|
2949
|
+
lineOffset(x, y) {
|
|
2950
|
+
switch (this.rotation) {
|
|
2951
|
+
case 0:
|
|
2952
|
+
return y - this.y;
|
|
2953
|
+
case 90:
|
|
2954
|
+
return this.x - x;
|
|
2955
|
+
// 90° CW: line axis is -x
|
|
2956
|
+
case 180:
|
|
2957
|
+
return this.y - y;
|
|
2958
|
+
case 270:
|
|
2959
|
+
return x - this.x;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
/** Whether the cursor is at the start of its line (char axis at origin) */
|
|
2963
|
+
atLineStart(x, y) {
|
|
2964
|
+
switch (this.rotation) {
|
|
2965
|
+
case 0:
|
|
2966
|
+
case 180:
|
|
2967
|
+
return x === this.x;
|
|
2968
|
+
case 90:
|
|
2969
|
+
case 270:
|
|
2970
|
+
return y === this.y;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2734
2973
|
commandForLanguage(language, config) {
|
|
2735
2974
|
return __async(this, null, function* () {
|
|
2736
2975
|
this.context = {
|
|
@@ -2777,9 +3016,10 @@ var Text = class extends LabelField {
|
|
|
2777
3016
|
const elementNode = rootNode;
|
|
2778
3017
|
const tag = elementNode.rawTagName;
|
|
2779
3018
|
if (tag == BREAK_TAG) {
|
|
3019
|
+
const linePos = this.advanceLine(initialX, initialY, font.size + this.lineSpacing);
|
|
2780
3020
|
return {
|
|
2781
|
-
x:
|
|
2782
|
-
y:
|
|
3021
|
+
x: linePos.x,
|
|
3022
|
+
y: linePos.y,
|
|
2783
3023
|
command: this.context.generator.commandGroup([])
|
|
2784
3024
|
};
|
|
2785
3025
|
}
|
|
@@ -2798,9 +3038,10 @@ var Text = class extends LabelField {
|
|
|
2798
3038
|
baseFont.style = "italic";
|
|
2799
3039
|
}
|
|
2800
3040
|
if (tag == PARAGRAPH_TAG) {
|
|
2801
|
-
if (initialX
|
|
2802
|
-
|
|
2803
|
-
|
|
3041
|
+
if (!this.atLineStart(initialX, initialY)) {
|
|
3042
|
+
const linePos = this.advanceLine(initialX, initialY, baseFont.size + this.lineSpacing);
|
|
3043
|
+
currentX = linePos.x;
|
|
3044
|
+
currentY = linePos.y;
|
|
2804
3045
|
}
|
|
2805
3046
|
}
|
|
2806
3047
|
elementNode.childNodes.forEach((node) => {
|
|
@@ -2811,8 +3052,9 @@ var Text = class extends LabelField {
|
|
|
2811
3052
|
});
|
|
2812
3053
|
if (tag == PARAGRAPH_TAG) {
|
|
2813
3054
|
if (!this.endsWithBreak(elementNode)) {
|
|
2814
|
-
|
|
2815
|
-
|
|
3055
|
+
const linePos = this.advanceLine(currentX, currentY, baseFont.size + this.lineSpacing);
|
|
3056
|
+
currentX = linePos.x;
|
|
3057
|
+
currentY = linePos.y;
|
|
2816
3058
|
}
|
|
2817
3059
|
}
|
|
2818
3060
|
return {
|
|
@@ -2832,21 +3074,23 @@ var Text = class extends LabelField {
|
|
|
2832
3074
|
const textWidhtFunction = this.textWidthFunction;
|
|
2833
3075
|
let fullWidth = textWidhtFunction(content, font);
|
|
2834
3076
|
if (this.width) {
|
|
2835
|
-
const initialPadding = initialX
|
|
3077
|
+
const initialPadding = this.charOffset(initialX, initialY);
|
|
2836
3078
|
let rowWidth = this.width - initialPadding;
|
|
2837
3079
|
if (rowWidth <= 0) {
|
|
2838
3080
|
rowWidth = this.width;
|
|
2839
|
-
|
|
2840
|
-
|
|
3081
|
+
const linePos = this.advanceLine(initialX, initialY, font.size + this.lineSpacing);
|
|
3082
|
+
initialX = linePos.x;
|
|
3083
|
+
initialY = linePos.y;
|
|
2841
3084
|
}
|
|
2842
|
-
if (initialX
|
|
3085
|
+
if (this.atLineStart(initialX, initialY)) {
|
|
2843
3086
|
content = content.trimStart();
|
|
2844
3087
|
fullWidth = textWidhtFunction(content, font);
|
|
2845
3088
|
}
|
|
2846
3089
|
if (fullWidth <= rowWidth) {
|
|
3090
|
+
const end = this.advanceChar(initialX, initialY, fullWidth);
|
|
2847
3091
|
return {
|
|
2848
|
-
x:
|
|
2849
|
-
y:
|
|
3092
|
+
x: end.x,
|
|
3093
|
+
y: end.y,
|
|
2850
3094
|
command: this.textCommand(content, initialX, initialY, font, features)
|
|
2851
3095
|
};
|
|
2852
3096
|
} else {
|
|
@@ -2860,8 +3104,9 @@ var Text = class extends LabelField {
|
|
|
2860
3104
|
let finalY = y;
|
|
2861
3105
|
do {
|
|
2862
3106
|
if (remainingWidth < rowWidth) {
|
|
2863
|
-
|
|
2864
|
-
|
|
3107
|
+
const end = this.advanceChar(x, y, remainingWidth);
|
|
3108
|
+
finalX = end.x;
|
|
3109
|
+
finalY = end.y;
|
|
2865
3110
|
commands.push(this.textCommand(remainingContent, x, y, font, features));
|
|
2866
3111
|
remainingContent = "";
|
|
2867
3112
|
} else {
|
|
@@ -2879,8 +3124,9 @@ var Text = class extends LabelField {
|
|
|
2879
3124
|
let originalRowEndIndex = rowEndIndex;
|
|
2880
3125
|
rowWidth = this.width;
|
|
2881
3126
|
if (rowEndIndex < 0) {
|
|
2882
|
-
|
|
2883
|
-
|
|
3127
|
+
const linePos2 = this.advanceLine(x, y, font.size + this.lineSpacing);
|
|
3128
|
+
x = linePos2.x;
|
|
3129
|
+
y = linePos2.y;
|
|
2884
3130
|
continue;
|
|
2885
3131
|
}
|
|
2886
3132
|
while (!(!isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1))) || isBreakAfterChar(remainingContent.charAt(rowEndIndex))) && rowEndIndex > 0) {
|
|
@@ -2958,12 +3204,14 @@ var Text = class extends LabelField {
|
|
|
2958
3204
|
const thisRow = remainingContent.substring(0, rowEndIndex + 1);
|
|
2959
3205
|
commands.push(this.textCommand(thisRow, x, y, font, features));
|
|
2960
3206
|
if (nextRowStartIndex == remainingContent.length) {
|
|
2961
|
-
|
|
2962
|
-
|
|
3207
|
+
const end = this.advanceChar(x, y, remainingWidth);
|
|
3208
|
+
finalX = end.x;
|
|
3209
|
+
finalY = end.y;
|
|
2963
3210
|
}
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
3211
|
+
const linePos = this.advanceLine(x, y, font.size + this.lineSpacing);
|
|
3212
|
+
x = linePos.x;
|
|
3213
|
+
y = linePos.y;
|
|
3214
|
+
currentHeight = this.lineOffset(x, y);
|
|
2967
3215
|
remainingContent = remainingContent.substring(nextRowStartIndex);
|
|
2968
3216
|
remainingWidth = textWidhtFunction(remainingContent, font);
|
|
2969
3217
|
}
|
|
@@ -2980,9 +3228,10 @@ var Text = class extends LabelField {
|
|
|
2980
3228
|
};
|
|
2981
3229
|
}
|
|
2982
3230
|
} else {
|
|
3231
|
+
const end = this.advanceChar(initialX, initialY, fullWidth);
|
|
2983
3232
|
return {
|
|
2984
|
-
x:
|
|
2985
|
-
y:
|
|
3233
|
+
x: end.x,
|
|
3234
|
+
y: end.y,
|
|
2986
3235
|
command: this.textCommand(content, initialX, initialY, font, features)
|
|
2987
3236
|
};
|
|
2988
3237
|
}
|
|
@@ -2995,7 +3244,7 @@ var Text = class extends LabelField {
|
|
|
2995
3244
|
const finalX = Math.round(x);
|
|
2996
3245
|
const finalY = Math.round(y);
|
|
2997
3246
|
let commands = [];
|
|
2998
|
-
const textCommand = this.context.generator.text(text, finalX, finalY, finalFont, finalFontSize);
|
|
3247
|
+
const textCommand = this.context.generator.text(text, finalX, finalY, finalFont, finalFontSize, this.rotation);
|
|
2999
3248
|
if (features.length == 0) {
|
|
3000
3249
|
return textCommand;
|
|
3001
3250
|
} else {
|
|
@@ -3012,13 +3261,28 @@ var Text = class extends LabelField {
|
|
|
3012
3261
|
return this.context.generator.commandGroup(commands);
|
|
3013
3262
|
}
|
|
3014
3263
|
textLineCommand(width, x, y, lineHeight, linePercentage, fontSize) {
|
|
3015
|
-
const
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3264
|
+
const offset = Math.round(fontSize * linePercentage - lineHeight / 2);
|
|
3265
|
+
let start;
|
|
3266
|
+
let end;
|
|
3267
|
+
switch (this.rotation) {
|
|
3268
|
+
case 0:
|
|
3269
|
+
start = { x: Math.round(x), y: Math.round(y) + offset };
|
|
3270
|
+
end = { x: Math.round(x) + Math.round(width), y: start.y };
|
|
3271
|
+
break;
|
|
3272
|
+
case 90:
|
|
3273
|
+
start = { x: Math.round(x) - offset, y: Math.round(y) };
|
|
3274
|
+
end = { x: start.x, y: Math.round(y) + Math.round(width) };
|
|
3275
|
+
break;
|
|
3276
|
+
case 180:
|
|
3277
|
+
start = { x: Math.round(x), y: Math.round(y) - offset };
|
|
3278
|
+
end = { x: Math.round(x) - Math.round(width), y: start.y };
|
|
3279
|
+
break;
|
|
3280
|
+
case 270:
|
|
3281
|
+
start = { x: Math.round(x) + offset, y: Math.round(y) };
|
|
3282
|
+
end = { x: start.x, y: Math.round(y) - Math.round(width) };
|
|
3283
|
+
break;
|
|
3284
|
+
}
|
|
3285
|
+
return this.context.generator.line(start, end, lineHeight);
|
|
3022
3286
|
}
|
|
3023
3287
|
getFontName(font) {
|
|
3024
3288
|
var _a;
|
|
@@ -3032,22 +3296,25 @@ var Text = class extends LabelField {
|
|
|
3032
3296
|
get textWidthFunction() {
|
|
3033
3297
|
var _a, _b, _c;
|
|
3034
3298
|
if (this.font.name == "default") {
|
|
3035
|
-
return this.defaultTextWidth;
|
|
3299
|
+
return (text, font) => this.defaultTextWidth(text, font);
|
|
3036
3300
|
} else {
|
|
3037
|
-
return (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.textWidth) != null ? _c : this.defaultTextWidth;
|
|
3301
|
+
return (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.textWidth) != null ? _c : (text, font) => this.defaultTextWidth(text, font);
|
|
3038
3302
|
}
|
|
3039
3303
|
}
|
|
3040
3304
|
/**
|
|
3041
|
-
*
|
|
3042
|
-
*
|
|
3305
|
+
* Fallback width estimate when no font metrics are available.
|
|
3306
|
+
* Uses the TSPL x-multiplication value (dotToPoint of the dot size) as
|
|
3307
|
+
* the per-character width, which matches the rendered width of font "0".
|
|
3043
3308
|
*/
|
|
3044
3309
|
defaultTextWidth(text, font) {
|
|
3045
|
-
|
|
3310
|
+
var _a, _b, _c;
|
|
3311
|
+
const dpi = (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.dpi) != null ? _c : 203;
|
|
3312
|
+
return text.length * dotToPoint(font.size, dpi);
|
|
3046
3313
|
}
|
|
3047
3314
|
};
|
|
3048
3315
|
|
|
3049
3316
|
// src/labels/fields/BarCode.ts
|
|
3050
|
-
var BarCode = class extends
|
|
3317
|
+
var BarCode = class extends RotatableLabelField {
|
|
3051
3318
|
/**
|
|
3052
3319
|
* @param content Content to encode
|
|
3053
3320
|
* @param x X coordinate in dots
|
|
@@ -3065,16 +3332,19 @@ var BarCode = class extends LabelField {
|
|
|
3065
3332
|
this.type = type;
|
|
3066
3333
|
this.height = height;
|
|
3067
3334
|
this.barWidth = barWidth;
|
|
3068
|
-
this.rotation = 0;
|
|
3069
3335
|
this.humanReadable = "none";
|
|
3070
3336
|
this.alignment = "left";
|
|
3071
3337
|
}
|
|
3072
|
-
setRotation(rotation) {
|
|
3073
|
-
this.rotation = rotation;
|
|
3074
|
-
}
|
|
3075
3338
|
setHumanReadable(humanReadable) {
|
|
3076
3339
|
this.humanReadable = humanReadable;
|
|
3077
3340
|
}
|
|
3341
|
+
setPosition(position) {
|
|
3342
|
+
this.x = position.x;
|
|
3343
|
+
this.y = position.y;
|
|
3344
|
+
}
|
|
3345
|
+
getPosition() {
|
|
3346
|
+
return { x: this.x, y: this.y };
|
|
3347
|
+
}
|
|
3078
3348
|
commandForLanguage(language, _config) {
|
|
3079
3349
|
return __async(this, null, function* () {
|
|
3080
3350
|
return yield this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment, this.barWidth);
|
|
@@ -3083,16 +3353,43 @@ var BarCode = class extends LabelField {
|
|
|
3083
3353
|
};
|
|
3084
3354
|
|
|
3085
3355
|
// src/labels/fields/Image.ts
|
|
3086
|
-
var Image2 = class _Image extends
|
|
3356
|
+
var Image2 = class _Image extends RotatableLabelField {
|
|
3087
3357
|
constructor(x, y, image2) {
|
|
3088
3358
|
super();
|
|
3089
3359
|
this.x = x;
|
|
3090
3360
|
this.y = y;
|
|
3091
3361
|
this.image = image2;
|
|
3092
3362
|
}
|
|
3363
|
+
setPosition(position) {
|
|
3364
|
+
this.x = position.x;
|
|
3365
|
+
this.y = position.y;
|
|
3366
|
+
}
|
|
3367
|
+
getPosition() {
|
|
3368
|
+
return { x: this.x, y: this.y };
|
|
3369
|
+
}
|
|
3093
3370
|
commandForLanguage(language, _config) {
|
|
3094
3371
|
return __async(this, null, function* () {
|
|
3095
|
-
|
|
3372
|
+
if (this.rotation === 0) {
|
|
3373
|
+
return yield this.commandGeneratorFor(language).image(this.image, this.x, this.y);
|
|
3374
|
+
}
|
|
3375
|
+
const srcW = this.image.width * 8;
|
|
3376
|
+
const srcH = this.image.height;
|
|
3377
|
+
const bitmap2 = ImageUtils.rotateBWBitmap(this.image, 360 - this.rotation);
|
|
3378
|
+
let dx = this.x;
|
|
3379
|
+
let dy = this.y;
|
|
3380
|
+
switch (this.rotation) {
|
|
3381
|
+
case 90:
|
|
3382
|
+
dx = this.x - srcH;
|
|
3383
|
+
break;
|
|
3384
|
+
case 180:
|
|
3385
|
+
dx = this.x - srcW;
|
|
3386
|
+
dy = this.y - srcH;
|
|
3387
|
+
break;
|
|
3388
|
+
case 270:
|
|
3389
|
+
dy = this.y - srcW;
|
|
3390
|
+
break;
|
|
3391
|
+
}
|
|
3392
|
+
return yield this.commandGeneratorFor(language).image(bitmap2, dx, dy);
|
|
3096
3393
|
});
|
|
3097
3394
|
}
|
|
3098
3395
|
/**
|
|
@@ -3113,7 +3410,7 @@ var Image2 = class _Image extends LabelField {
|
|
|
3113
3410
|
};
|
|
3114
3411
|
|
|
3115
3412
|
// src/labels/fields/QRCode.ts
|
|
3116
|
-
var QRCode = class extends
|
|
3413
|
+
var QRCode = class extends RotatableLabelField {
|
|
3117
3414
|
constructor(content, x, y, width) {
|
|
3118
3415
|
super();
|
|
3119
3416
|
this.content = content;
|
|
@@ -3121,9 +3418,16 @@ var QRCode = class extends LabelField {
|
|
|
3121
3418
|
this.y = y;
|
|
3122
3419
|
this.width = width;
|
|
3123
3420
|
}
|
|
3421
|
+
setPosition(position) {
|
|
3422
|
+
this.x = position.x;
|
|
3423
|
+
this.y = position.y;
|
|
3424
|
+
}
|
|
3425
|
+
getPosition() {
|
|
3426
|
+
return { x: this.x, y: this.y };
|
|
3427
|
+
}
|
|
3124
3428
|
commandForLanguage(language, config) {
|
|
3125
3429
|
return __async(this, null, function* () {
|
|
3126
|
-
return yield this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y);
|
|
3430
|
+
return yield this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y, this.rotation);
|
|
3127
3431
|
});
|
|
3128
3432
|
}
|
|
3129
3433
|
};
|