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.mjs
CHANGED
|
@@ -246,6 +246,19 @@ function dotToPoint(dots, dpi) {
|
|
|
246
246
|
const inch = dots / dpi;
|
|
247
247
|
return Math.round(inch * pointsPerInch);
|
|
248
248
|
}
|
|
249
|
+
function inToDot(inches, dpi, round = false) {
|
|
250
|
+
const res = inches * dpi;
|
|
251
|
+
if (round) return Math.round(res);
|
|
252
|
+
else return res;
|
|
253
|
+
}
|
|
254
|
+
function mmToDot(mm, dpi, round = false) {
|
|
255
|
+
const res = mm / 25.4 * dpi;
|
|
256
|
+
if (round) return Math.round(res);
|
|
257
|
+
else return res;
|
|
258
|
+
}
|
|
259
|
+
function unitToDot(value, dpi, unitSystem, round = false) {
|
|
260
|
+
return unitSystem === "imperial" ? inToDot(value, dpi, round) : mmToDot(value, dpi, round);
|
|
261
|
+
}
|
|
249
262
|
|
|
250
263
|
// src/helpers/ImageDataParser.ts
|
|
251
264
|
function parsePNG(buffer2) {
|
|
@@ -496,7 +509,6 @@ var ImageProcessor = class {
|
|
|
496
509
|
*/
|
|
497
510
|
static getImageDataNode(image2, _target) {
|
|
498
511
|
return __async(this, null, function* () {
|
|
499
|
-
console.log("Processing image in Node.js environment");
|
|
500
512
|
if (image2 instanceof Blob) {
|
|
501
513
|
throw new Error("Blob input not supported in Node.js environment. Use file path or data URL instead.");
|
|
502
514
|
}
|
|
@@ -665,7 +677,6 @@ var ImageProcessor = class {
|
|
|
665
677
|
*/
|
|
666
678
|
static parse(buffer2, extension) {
|
|
667
679
|
const normalizedExtension = extension.startsWith(".") ? extension.slice(1) : extension;
|
|
668
|
-
console.log(`Parsing image with extension: ${normalizedExtension}`);
|
|
669
680
|
if (normalizedExtension === "png") {
|
|
670
681
|
return parsePNG(buffer2);
|
|
671
682
|
} else if (normalizedExtension === "jpeg" || normalizedExtension === "jpg") {
|
|
@@ -1079,6 +1090,54 @@ ${widthBits} ${height}
|
|
|
1079
1090
|
fs.writeFileSync(filePath, bytes);
|
|
1080
1091
|
});
|
|
1081
1092
|
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Rotate a BW bitmap by 90, 180 or 270 degrees clockwise.
|
|
1095
|
+
* The bitmap uses 0=black, 1=white with MSB-first packing.
|
|
1096
|
+
*/
|
|
1097
|
+
static rotateBWBitmap(bitmap2, rotation) {
|
|
1098
|
+
const srcWidthBytes = bitmap2.width;
|
|
1099
|
+
const srcWidthBits = srcWidthBytes * 8;
|
|
1100
|
+
const srcHeight = bitmap2.height;
|
|
1101
|
+
const src = bitmap2.bytes;
|
|
1102
|
+
const getBit = (col, row) => {
|
|
1103
|
+
const byteIndex = row * srcWidthBytes + (col >> 3);
|
|
1104
|
+
const bitIndex = 7 - (col & 7);
|
|
1105
|
+
return src[byteIndex] >> bitIndex & 1;
|
|
1106
|
+
};
|
|
1107
|
+
let dstWidthBits;
|
|
1108
|
+
let dstHeight;
|
|
1109
|
+
let getNewPixel;
|
|
1110
|
+
if (rotation === 90) {
|
|
1111
|
+
dstWidthBits = srcHeight;
|
|
1112
|
+
dstHeight = srcWidthBits;
|
|
1113
|
+
getNewPixel = (col, row) => getBit(srcWidthBits - 1 - row, col);
|
|
1114
|
+
} else if (rotation === 270) {
|
|
1115
|
+
dstWidthBits = srcHeight;
|
|
1116
|
+
dstHeight = srcWidthBits;
|
|
1117
|
+
getNewPixel = (col, row) => getBit(row, srcHeight - 1 - col);
|
|
1118
|
+
} else {
|
|
1119
|
+
dstWidthBits = srcWidthBits;
|
|
1120
|
+
dstHeight = srcHeight;
|
|
1121
|
+
getNewPixel = (col, row) => getBit(srcWidthBits - 1 - col, srcHeight - 1 - row);
|
|
1122
|
+
}
|
|
1123
|
+
const dstPad = dstWidthBits % 8 === 0 ? 0 : 8 - dstWidthBits % 8;
|
|
1124
|
+
const dstWidthBitsPadded = dstWidthBits + dstPad;
|
|
1125
|
+
const dstWidthBytes = dstWidthBitsPadded / 8;
|
|
1126
|
+
const dst = new Uint8Array(dstWidthBytes * dstHeight).fill(255);
|
|
1127
|
+
for (let row = 0; row < dstHeight; row++) {
|
|
1128
|
+
for (let col = 0; col < dstWidthBits; col++) {
|
|
1129
|
+
const bit = getNewPixel(col, row);
|
|
1130
|
+
const byteIndex = row * dstWidthBytes + (col >> 3);
|
|
1131
|
+
const mask = 1 << 7 - (col & 7);
|
|
1132
|
+
if (bit === 1) {
|
|
1133
|
+
dst[byteIndex] |= mask;
|
|
1134
|
+
} else {
|
|
1135
|
+
dst[byteIndex] &= ~mask & 255;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
return { width: dstWidthBytes, height: dstHeight, bytes: dst };
|
|
1140
|
+
}
|
|
1082
1141
|
static dilateOnce(bitmap2) {
|
|
1083
1142
|
const widthBytes = bitmap2.width;
|
|
1084
1143
|
const widthBits = widthBytes * 8;
|
|
@@ -1180,20 +1239,6 @@ var TSPLBitmapCommand = class _TSPLBitmapCommand extends TSPLVisualCommand {
|
|
|
1180
1239
|
}
|
|
1181
1240
|
};
|
|
1182
1241
|
|
|
1183
|
-
// src/commands/tspl/types.ts
|
|
1184
|
-
var alignmentToNumber = (alignment) => {
|
|
1185
|
-
switch (alignment) {
|
|
1186
|
-
case void 0:
|
|
1187
|
-
return 0;
|
|
1188
|
-
case "left":
|
|
1189
|
-
return 1;
|
|
1190
|
-
case "center":
|
|
1191
|
-
return 2;
|
|
1192
|
-
case "right":
|
|
1193
|
-
return 3;
|
|
1194
|
-
}
|
|
1195
|
-
};
|
|
1196
|
-
|
|
1197
1242
|
// src/commands/tspl/commands/basic/TSPLTextCommand.ts
|
|
1198
1243
|
var TSPLTextCommand = class extends TSPLVisualCommand {
|
|
1199
1244
|
constructor(content, x, y, font, rotation, xMultiplication, yMultiplication, alignment) {
|
|
@@ -1484,9 +1529,9 @@ var TSPLCommandGenerator = class _TSPLCommandGenerator {
|
|
|
1484
1529
|
print(sets, copiesPerSet) {
|
|
1485
1530
|
return new TSPLPrintCommand(sets, copiesPerSet);
|
|
1486
1531
|
}
|
|
1487
|
-
text(content, x, y, font, size) {
|
|
1532
|
+
text(content, x, y, font, size, rotation) {
|
|
1488
1533
|
const fontName = font == "default" ? "0" : font;
|
|
1489
|
-
return new TSPLTextCommand(content, x, y, fontName, 0, size, size, "left");
|
|
1534
|
+
return new TSPLTextCommand(content, x, y, fontName, rotation != null ? rotation : 0, size, size, "left");
|
|
1490
1535
|
}
|
|
1491
1536
|
upload(name, data) {
|
|
1492
1537
|
return new TSPLDownload(name, data);
|
|
@@ -1513,10 +1558,10 @@ var TSPLCommandGenerator = class _TSPLCommandGenerator {
|
|
|
1513
1558
|
image(image2, x, y, mode) {
|
|
1514
1559
|
return new TSPLBitmapCommand(image2, x, y, mode);
|
|
1515
1560
|
}
|
|
1516
|
-
qrCode(content, width, x, y) {
|
|
1561
|
+
qrCode(content, width, x, y, rotation) {
|
|
1517
1562
|
const cellCount = this.cellCount(content);
|
|
1518
1563
|
const cellWidth = Math.round(width / cellCount);
|
|
1519
|
-
return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M");
|
|
1564
|
+
return new TSPLQRCommand(`A${content}`, x, y, cellWidth, "H", "M", rotation != null ? rotation : 0);
|
|
1520
1565
|
}
|
|
1521
1566
|
barCode(content, x, y, type, height, rotation, humanReadable, alignment, barWidth = 2) {
|
|
1522
1567
|
const { narrow, wide } = _TSPLCommandGenerator.narrowWideFor(type, barWidth);
|
|
@@ -1566,6 +1611,20 @@ var TSPLCommandGenerator = class _TSPLCommandGenerator {
|
|
|
1566
1611
|
};
|
|
1567
1612
|
var TSPLCommandGenerator_default = new TSPLCommandGenerator();
|
|
1568
1613
|
|
|
1614
|
+
// src/commands/tspl/types.ts
|
|
1615
|
+
var alignmentToNumber = (alignment) => {
|
|
1616
|
+
switch (alignment) {
|
|
1617
|
+
case void 0:
|
|
1618
|
+
return 0;
|
|
1619
|
+
case "left":
|
|
1620
|
+
return 1;
|
|
1621
|
+
case "center":
|
|
1622
|
+
return 2;
|
|
1623
|
+
case "right":
|
|
1624
|
+
return 3;
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1569
1628
|
// src/printers/index.ts
|
|
1570
1629
|
var printers_exports = {};
|
|
1571
1630
|
__export(printers_exports, {
|
|
@@ -2393,7 +2452,7 @@ var Printable = class {
|
|
|
2393
2452
|
/**
|
|
2394
2453
|
* 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
|
|
2395
2454
|
* @param printer Printer to generate the command. Important because the command is printer language specific
|
|
2396
|
-
* @returns A promise for a command. Most commands are
|
|
2455
|
+
* @returns A promise for a command. Most commands are synchronous but some may require to access async resources
|
|
2397
2456
|
*/
|
|
2398
2457
|
commandForPrinter(printer, config) {
|
|
2399
2458
|
return __async(this, null, function* () {
|
|
@@ -2412,8 +2471,105 @@ var Printable = class {
|
|
|
2412
2471
|
}
|
|
2413
2472
|
};
|
|
2414
2473
|
|
|
2474
|
+
// src/labels/types.ts
|
|
2475
|
+
var rotationForOrientation = (orientation) => {
|
|
2476
|
+
switch (orientation) {
|
|
2477
|
+
case "normal":
|
|
2478
|
+
return 0;
|
|
2479
|
+
case "left":
|
|
2480
|
+
return 90;
|
|
2481
|
+
case "upside-down":
|
|
2482
|
+
return 180;
|
|
2483
|
+
case "right":
|
|
2484
|
+
return 270;
|
|
2485
|
+
}
|
|
2486
|
+
};
|
|
2487
|
+
|
|
2415
2488
|
// src/labels/Label.ts
|
|
2416
2489
|
import * as fontkit from "fontkit";
|
|
2490
|
+
|
|
2491
|
+
// src/labels/fields/superClasses/LabelField.ts
|
|
2492
|
+
var LabelField = class extends Printable {
|
|
2493
|
+
};
|
|
2494
|
+
|
|
2495
|
+
// src/labels/fields/superClasses/RotatableLabelField.ts
|
|
2496
|
+
var RotatableLabelField = class extends LabelField {
|
|
2497
|
+
constructor() {
|
|
2498
|
+
super(...arguments);
|
|
2499
|
+
this.rotation = 0;
|
|
2500
|
+
}
|
|
2501
|
+
setRotation(rotation) {
|
|
2502
|
+
this.rotation = rotation;
|
|
2503
|
+
}
|
|
2504
|
+
getRotation() {
|
|
2505
|
+
return this.rotation;
|
|
2506
|
+
}
|
|
2507
|
+
};
|
|
2508
|
+
|
|
2509
|
+
// src/labels/RotatableContainer.ts
|
|
2510
|
+
var RotatableContainer = class extends RotatableLabelField {
|
|
2511
|
+
/**
|
|
2512
|
+
* @param size Size in dots
|
|
2513
|
+
*/
|
|
2514
|
+
constructor(size) {
|
|
2515
|
+
super();
|
|
2516
|
+
this.fields = [];
|
|
2517
|
+
this.size = size;
|
|
2518
|
+
}
|
|
2519
|
+
/**
|
|
2520
|
+
* Place fields in the container
|
|
2521
|
+
* @param fields
|
|
2522
|
+
*/
|
|
2523
|
+
add(...fields) {
|
|
2524
|
+
this.fields.push(...fields);
|
|
2525
|
+
}
|
|
2526
|
+
commandForLanguage(language, config) {
|
|
2527
|
+
return __async(this, null, function* () {
|
|
2528
|
+
const commandList = yield Promise.all(this.fields.map((field) => this.rotationAdjustedCommand(field, language, config)));
|
|
2529
|
+
return this.commandGeneratorFor(language).commandGroup(commandList);
|
|
2530
|
+
});
|
|
2531
|
+
}
|
|
2532
|
+
rotationAdjustedCommand(field, language, config) {
|
|
2533
|
+
return __async(this, null, function* () {
|
|
2534
|
+
let originalRotation = void 0;
|
|
2535
|
+
let originalPosition = void 0;
|
|
2536
|
+
if (field.hasOwnProperty("rotation")) {
|
|
2537
|
+
const rotatableField = field;
|
|
2538
|
+
originalRotation = rotatableField.getRotation();
|
|
2539
|
+
rotatableField.setRotation((originalRotation + this.rotation) % 360);
|
|
2540
|
+
}
|
|
2541
|
+
if (typeof field.getPosition === "function" && typeof field.setPosition === "function") {
|
|
2542
|
+
const positionedField = field;
|
|
2543
|
+
originalPosition = positionedField.getPosition();
|
|
2544
|
+
positionedField.setPosition(this.adjustPosition(originalPosition));
|
|
2545
|
+
}
|
|
2546
|
+
const command = yield field.commandForLanguage(language, config);
|
|
2547
|
+
if (originalRotation !== void 0) {
|
|
2548
|
+
const rotatableField = field;
|
|
2549
|
+
rotatableField.setRotation(originalRotation);
|
|
2550
|
+
}
|
|
2551
|
+
if (originalPosition !== void 0) {
|
|
2552
|
+
const positionedField = field;
|
|
2553
|
+
positionedField.setPosition(originalPosition);
|
|
2554
|
+
}
|
|
2555
|
+
return command;
|
|
2556
|
+
});
|
|
2557
|
+
}
|
|
2558
|
+
adjustPosition(position) {
|
|
2559
|
+
switch (this.rotation) {
|
|
2560
|
+
case 90:
|
|
2561
|
+
return { x: this.size.height - position.y, y: position.x };
|
|
2562
|
+
case 180:
|
|
2563
|
+
return { x: this.size.width - position.x, y: this.size.height - position.y };
|
|
2564
|
+
case 270:
|
|
2565
|
+
return { x: position.y, y: this.size.width - position.x };
|
|
2566
|
+
default:
|
|
2567
|
+
return position;
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
};
|
|
2571
|
+
|
|
2572
|
+
// src/labels/Label.ts
|
|
2417
2573
|
var DEFAULT_FONT_WEIGHT = 400;
|
|
2418
2574
|
var DEFAULT_FONT_STYLE = "normal";
|
|
2419
2575
|
var FONT_PREFIX = "f";
|
|
@@ -2422,10 +2578,7 @@ var Label = class extends Printable {
|
|
|
2422
2578
|
super();
|
|
2423
2579
|
this.fonts = {};
|
|
2424
2580
|
this.density = 8;
|
|
2425
|
-
|
|
2426
|
-
* List of fields on the label
|
|
2427
|
-
*/
|
|
2428
|
-
this.fields = [];
|
|
2581
|
+
this.orientation = "normal";
|
|
2429
2582
|
this.fontCounter = 0;
|
|
2430
2583
|
this._textWidthCorrectionFactor = 0.935;
|
|
2431
2584
|
this.width = width;
|
|
@@ -2433,6 +2586,9 @@ var Label = class extends Printable {
|
|
|
2433
2586
|
this.unitSystem = dimensionUnit;
|
|
2434
2587
|
this.dpi = dpi;
|
|
2435
2588
|
this.density = density;
|
|
2589
|
+
const widthInDots = unitToDot(width, dpi, dimensionUnit);
|
|
2590
|
+
const heightInDots = unitToDot(height, dpi, dimensionUnit);
|
|
2591
|
+
this.container = new RotatableContainer({ width: widthInDots, height: heightInDots });
|
|
2436
2592
|
}
|
|
2437
2593
|
/**
|
|
2438
2594
|
* Configuration used when generating commands
|
|
@@ -2463,11 +2619,17 @@ var Label = class extends Printable {
|
|
|
2463
2619
|
setTextWidthCorrectionFactor(factor) {
|
|
2464
2620
|
this._textWidthCorrectionFactor = factor;
|
|
2465
2621
|
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Change the orientation the label is printed in. This will rotate all fields in the container
|
|
2624
|
+
* @param orientation
|
|
2625
|
+
*/
|
|
2626
|
+
setOrientation(orientation) {
|
|
2627
|
+
this.orientation = orientation;
|
|
2628
|
+
this.container.setRotation(rotationForOrientation(orientation));
|
|
2629
|
+
}
|
|
2466
2630
|
commandForLanguage(language, config) {
|
|
2467
2631
|
return __async(this, null, function* () {
|
|
2468
|
-
|
|
2469
|
-
const commandList = yield Promise.all(this.fields.map((field) => field.commandForLanguage(language, configuration)));
|
|
2470
|
-
return this.commandGeneratorFor(language).commandGroup(commandList);
|
|
2632
|
+
return yield this.container.commandForLanguage(language, config);
|
|
2471
2633
|
});
|
|
2472
2634
|
}
|
|
2473
2635
|
/**
|
|
@@ -2475,7 +2637,7 @@ var Label = class extends Printable {
|
|
|
2475
2637
|
* @param fields
|
|
2476
2638
|
*/
|
|
2477
2639
|
add(...fields) {
|
|
2478
|
-
this.
|
|
2640
|
+
this.container.add(...fields);
|
|
2479
2641
|
}
|
|
2480
2642
|
/**
|
|
2481
2643
|
* Register a font to be used. Use the name provided in components to use the font.
|
|
@@ -2541,11 +2703,17 @@ var Label = class extends Printable {
|
|
|
2541
2703
|
*/
|
|
2542
2704
|
fullCommand(language, gap, direction, mirror = false, gapOffset = 0, generator) {
|
|
2543
2705
|
return __async(this, null, function* () {
|
|
2706
|
+
let finalDimations;
|
|
2707
|
+
if (this.orientation == "normal" || this.orientation == "upside-down") {
|
|
2708
|
+
finalDimations = { width: this.width, height: this.height };
|
|
2709
|
+
} else {
|
|
2710
|
+
finalDimations = { width: this.height, height: this.width };
|
|
2711
|
+
}
|
|
2544
2712
|
const commands = [
|
|
2545
2713
|
this.fontUploadCommands(generator),
|
|
2546
2714
|
generator.setUp(
|
|
2547
|
-
|
|
2548
|
-
|
|
2715
|
+
finalDimations.width,
|
|
2716
|
+
finalDimations.height,
|
|
2549
2717
|
gap,
|
|
2550
2718
|
gapOffset,
|
|
2551
2719
|
direction,
|
|
@@ -2576,10 +2744,10 @@ var Label = class extends Printable {
|
|
|
2576
2744
|
const family = this.fonts[font.name];
|
|
2577
2745
|
if (!family) return null;
|
|
2578
2746
|
const style = (_a = font.style) != null ? _a : DEFAULT_FONT_STYLE;
|
|
2579
|
-
const
|
|
2747
|
+
const weight = (_b = font.weight) != null ? _b : DEFAULT_FONT_WEIGHT;
|
|
2580
2748
|
const fontKeys = Object.keys(family.fonts);
|
|
2581
2749
|
const exactMatch = fontKeys.find(
|
|
2582
|
-
(key) => family.fonts[key].style == style && family.fonts[key].weight ==
|
|
2750
|
+
(key) => family.fonts[key].style == style && family.fonts[key].weight == weight
|
|
2583
2751
|
);
|
|
2584
2752
|
if (exactMatch) {
|
|
2585
2753
|
return family.fonts[exactMatch];
|
|
@@ -2589,7 +2757,7 @@ var Label = class extends Printable {
|
|
|
2589
2757
|
let weigthDiff = 99999999;
|
|
2590
2758
|
let selectedKey = "";
|
|
2591
2759
|
sameStyleKeys.forEach((key) => {
|
|
2592
|
-
const diff = Math.abs(
|
|
2760
|
+
const diff = Math.abs(weight - family.fonts[key].weight);
|
|
2593
2761
|
if (diff < weigthDiff) {
|
|
2594
2762
|
weigthDiff = diff;
|
|
2595
2763
|
selectedKey = key;
|
|
@@ -2617,10 +2785,6 @@ var Label = class extends Printable {
|
|
|
2617
2785
|
}
|
|
2618
2786
|
};
|
|
2619
2787
|
|
|
2620
|
-
// src/labels/fields/LabelField.ts
|
|
2621
|
-
var LabelField = class extends Printable {
|
|
2622
|
-
};
|
|
2623
|
-
|
|
2624
2788
|
// src/labels/fields/Line.ts
|
|
2625
2789
|
var Line = class extends LabelField {
|
|
2626
2790
|
/**
|
|
@@ -2649,7 +2813,7 @@ var UNDERLINE_TAG = "u";
|
|
|
2649
2813
|
var STRIKE_TAG = ["s", "del", "strike"];
|
|
2650
2814
|
var PARAGRAPH_TAG = "p";
|
|
2651
2815
|
var BREAK_TAG = "br";
|
|
2652
|
-
var Text = class extends
|
|
2816
|
+
var Text = class extends RotatableLabelField {
|
|
2653
2817
|
constructor(content, x, y, formatted = true) {
|
|
2654
2818
|
super();
|
|
2655
2819
|
this.font = { name: "default", size: 10 };
|
|
@@ -2679,6 +2843,13 @@ var Text = class extends LabelField {
|
|
|
2679
2843
|
}
|
|
2680
2844
|
return false;
|
|
2681
2845
|
}
|
|
2846
|
+
setPosition(position) {
|
|
2847
|
+
this.x = position.x;
|
|
2848
|
+
this.y = position.y;
|
|
2849
|
+
}
|
|
2850
|
+
getPosition() {
|
|
2851
|
+
return { x: this.x, y: this.y };
|
|
2852
|
+
}
|
|
2682
2853
|
/**
|
|
2683
2854
|
* Sets the field to single line
|
|
2684
2855
|
* @param width Max width of the text. Leave it undefined to allow the field to grow
|
|
@@ -2699,13 +2870,81 @@ var Text = class extends LabelField {
|
|
|
2699
2870
|
this.height = height;
|
|
2700
2871
|
}
|
|
2701
2872
|
/**
|
|
2702
|
-
* Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used
|
|
2873
|
+
* Set a font to use as a base. If no formatting is set on the text with a html tag, this will be used
|
|
2703
2874
|
* Note: The font name either has to be a built in font on your printer or a font
|
|
2704
2875
|
* that is registered on the label using 'registerFont'.
|
|
2705
2876
|
*/
|
|
2706
2877
|
setFont(font) {
|
|
2707
2878
|
this.font = font;
|
|
2708
2879
|
}
|
|
2880
|
+
// --- Rotation-aware position helpers ---
|
|
2881
|
+
/** Advance cursor by `amount` along the character direction */
|
|
2882
|
+
advanceChar(x, y, amount) {
|
|
2883
|
+
switch (this.rotation) {
|
|
2884
|
+
case 0:
|
|
2885
|
+
return { x: x + amount, y };
|
|
2886
|
+
case 90:
|
|
2887
|
+
return { x, y: y + amount };
|
|
2888
|
+
// 90° CW: chars go downward
|
|
2889
|
+
case 180:
|
|
2890
|
+
return { x: x - amount, y };
|
|
2891
|
+
case 270:
|
|
2892
|
+
return { x, y: y - amount };
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
/** Advance to the next line (reset char axis, advance in line direction) */
|
|
2896
|
+
advanceLine(x, y, lineHeight) {
|
|
2897
|
+
switch (this.rotation) {
|
|
2898
|
+
case 0:
|
|
2899
|
+
return { x: this.x, y: y + lineHeight };
|
|
2900
|
+
case 90:
|
|
2901
|
+
return { x: x - lineHeight, y: this.y };
|
|
2902
|
+
// 90° CW: lines stack leftward (-x)
|
|
2903
|
+
case 180:
|
|
2904
|
+
return { x: this.x, y: y - lineHeight };
|
|
2905
|
+
case 270:
|
|
2906
|
+
return { x: x + lineHeight, y: this.y };
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
/** How far into the current line the cursor is (for width constraint calc) */
|
|
2910
|
+
charOffset(x, y) {
|
|
2911
|
+
switch (this.rotation) {
|
|
2912
|
+
case 0:
|
|
2913
|
+
return x - this.x;
|
|
2914
|
+
case 90:
|
|
2915
|
+
return y - this.y;
|
|
2916
|
+
// 90° CW: char axis is +y
|
|
2917
|
+
case 180:
|
|
2918
|
+
return this.x - x;
|
|
2919
|
+
case 270:
|
|
2920
|
+
return this.y - y;
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
/** How many lines deep we are (for height constraint calc) */
|
|
2924
|
+
lineOffset(x, y) {
|
|
2925
|
+
switch (this.rotation) {
|
|
2926
|
+
case 0:
|
|
2927
|
+
return y - this.y;
|
|
2928
|
+
case 90:
|
|
2929
|
+
return this.x - x;
|
|
2930
|
+
// 90° CW: line axis is -x
|
|
2931
|
+
case 180:
|
|
2932
|
+
return this.y - y;
|
|
2933
|
+
case 270:
|
|
2934
|
+
return x - this.x;
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
/** Whether the cursor is at the start of its line (char axis at origin) */
|
|
2938
|
+
atLineStart(x, y) {
|
|
2939
|
+
switch (this.rotation) {
|
|
2940
|
+
case 0:
|
|
2941
|
+
case 180:
|
|
2942
|
+
return x === this.x;
|
|
2943
|
+
case 90:
|
|
2944
|
+
case 270:
|
|
2945
|
+
return y === this.y;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2709
2948
|
commandForLanguage(language, config) {
|
|
2710
2949
|
return __async(this, null, function* () {
|
|
2711
2950
|
this.context = {
|
|
@@ -2752,9 +2991,10 @@ var Text = class extends LabelField {
|
|
|
2752
2991
|
const elementNode = rootNode;
|
|
2753
2992
|
const tag = elementNode.rawTagName;
|
|
2754
2993
|
if (tag == BREAK_TAG) {
|
|
2994
|
+
const linePos = this.advanceLine(initialX, initialY, font.size + this.lineSpacing);
|
|
2755
2995
|
return {
|
|
2756
|
-
x:
|
|
2757
|
-
y:
|
|
2996
|
+
x: linePos.x,
|
|
2997
|
+
y: linePos.y,
|
|
2758
2998
|
command: this.context.generator.commandGroup([])
|
|
2759
2999
|
};
|
|
2760
3000
|
}
|
|
@@ -2773,9 +3013,10 @@ var Text = class extends LabelField {
|
|
|
2773
3013
|
baseFont.style = "italic";
|
|
2774
3014
|
}
|
|
2775
3015
|
if (tag == PARAGRAPH_TAG) {
|
|
2776
|
-
if (initialX
|
|
2777
|
-
|
|
2778
|
-
|
|
3016
|
+
if (!this.atLineStart(initialX, initialY)) {
|
|
3017
|
+
const linePos = this.advanceLine(initialX, initialY, baseFont.size + this.lineSpacing);
|
|
3018
|
+
currentX = linePos.x;
|
|
3019
|
+
currentY = linePos.y;
|
|
2779
3020
|
}
|
|
2780
3021
|
}
|
|
2781
3022
|
elementNode.childNodes.forEach((node) => {
|
|
@@ -2786,8 +3027,9 @@ var Text = class extends LabelField {
|
|
|
2786
3027
|
});
|
|
2787
3028
|
if (tag == PARAGRAPH_TAG) {
|
|
2788
3029
|
if (!this.endsWithBreak(elementNode)) {
|
|
2789
|
-
|
|
2790
|
-
|
|
3030
|
+
const linePos = this.advanceLine(currentX, currentY, baseFont.size + this.lineSpacing);
|
|
3031
|
+
currentX = linePos.x;
|
|
3032
|
+
currentY = linePos.y;
|
|
2791
3033
|
}
|
|
2792
3034
|
}
|
|
2793
3035
|
return {
|
|
@@ -2807,21 +3049,23 @@ var Text = class extends LabelField {
|
|
|
2807
3049
|
const textWidhtFunction = this.textWidthFunction;
|
|
2808
3050
|
let fullWidth = textWidhtFunction(content, font);
|
|
2809
3051
|
if (this.width) {
|
|
2810
|
-
const initialPadding = initialX
|
|
3052
|
+
const initialPadding = this.charOffset(initialX, initialY);
|
|
2811
3053
|
let rowWidth = this.width - initialPadding;
|
|
2812
3054
|
if (rowWidth <= 0) {
|
|
2813
3055
|
rowWidth = this.width;
|
|
2814
|
-
|
|
2815
|
-
|
|
3056
|
+
const linePos = this.advanceLine(initialX, initialY, font.size + this.lineSpacing);
|
|
3057
|
+
initialX = linePos.x;
|
|
3058
|
+
initialY = linePos.y;
|
|
2816
3059
|
}
|
|
2817
|
-
if (initialX
|
|
3060
|
+
if (this.atLineStart(initialX, initialY)) {
|
|
2818
3061
|
content = content.trimStart();
|
|
2819
3062
|
fullWidth = textWidhtFunction(content, font);
|
|
2820
3063
|
}
|
|
2821
3064
|
if (fullWidth <= rowWidth) {
|
|
3065
|
+
const end = this.advanceChar(initialX, initialY, fullWidth);
|
|
2822
3066
|
return {
|
|
2823
|
-
x:
|
|
2824
|
-
y:
|
|
3067
|
+
x: end.x,
|
|
3068
|
+
y: end.y,
|
|
2825
3069
|
command: this.textCommand(content, initialX, initialY, font, features)
|
|
2826
3070
|
};
|
|
2827
3071
|
} else {
|
|
@@ -2835,8 +3079,9 @@ var Text = class extends LabelField {
|
|
|
2835
3079
|
let finalY = y;
|
|
2836
3080
|
do {
|
|
2837
3081
|
if (remainingWidth < rowWidth) {
|
|
2838
|
-
|
|
2839
|
-
|
|
3082
|
+
const end = this.advanceChar(x, y, remainingWidth);
|
|
3083
|
+
finalX = end.x;
|
|
3084
|
+
finalY = end.y;
|
|
2840
3085
|
commands.push(this.textCommand(remainingContent, x, y, font, features));
|
|
2841
3086
|
remainingContent = "";
|
|
2842
3087
|
} else {
|
|
@@ -2854,8 +3099,9 @@ var Text = class extends LabelField {
|
|
|
2854
3099
|
let originalRowEndIndex = rowEndIndex;
|
|
2855
3100
|
rowWidth = this.width;
|
|
2856
3101
|
if (rowEndIndex < 0) {
|
|
2857
|
-
|
|
2858
|
-
|
|
3102
|
+
const linePos2 = this.advanceLine(x, y, font.size + this.lineSpacing);
|
|
3103
|
+
x = linePos2.x;
|
|
3104
|
+
y = linePos2.y;
|
|
2859
3105
|
continue;
|
|
2860
3106
|
}
|
|
2861
3107
|
while (!(!isWhitespace(remainingContent.charAt(rowEndIndex)) && (rowEndIndex == remainingContent.length - 1 || isWhitespace(remainingContent.charAt(rowEndIndex + 1))) || isBreakAfterChar(remainingContent.charAt(rowEndIndex))) && rowEndIndex > 0) {
|
|
@@ -2933,12 +3179,14 @@ var Text = class extends LabelField {
|
|
|
2933
3179
|
const thisRow = remainingContent.substring(0, rowEndIndex + 1);
|
|
2934
3180
|
commands.push(this.textCommand(thisRow, x, y, font, features));
|
|
2935
3181
|
if (nextRowStartIndex == remainingContent.length) {
|
|
2936
|
-
|
|
2937
|
-
|
|
3182
|
+
const end = this.advanceChar(x, y, remainingWidth);
|
|
3183
|
+
finalX = end.x;
|
|
3184
|
+
finalY = end.y;
|
|
2938
3185
|
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
3186
|
+
const linePos = this.advanceLine(x, y, font.size + this.lineSpacing);
|
|
3187
|
+
x = linePos.x;
|
|
3188
|
+
y = linePos.y;
|
|
3189
|
+
currentHeight = this.lineOffset(x, y);
|
|
2942
3190
|
remainingContent = remainingContent.substring(nextRowStartIndex);
|
|
2943
3191
|
remainingWidth = textWidhtFunction(remainingContent, font);
|
|
2944
3192
|
}
|
|
@@ -2955,9 +3203,10 @@ var Text = class extends LabelField {
|
|
|
2955
3203
|
};
|
|
2956
3204
|
}
|
|
2957
3205
|
} else {
|
|
3206
|
+
const end = this.advanceChar(initialX, initialY, fullWidth);
|
|
2958
3207
|
return {
|
|
2959
|
-
x:
|
|
2960
|
-
y:
|
|
3208
|
+
x: end.x,
|
|
3209
|
+
y: end.y,
|
|
2961
3210
|
command: this.textCommand(content, initialX, initialY, font, features)
|
|
2962
3211
|
};
|
|
2963
3212
|
}
|
|
@@ -2970,7 +3219,7 @@ var Text = class extends LabelField {
|
|
|
2970
3219
|
const finalX = Math.round(x);
|
|
2971
3220
|
const finalY = Math.round(y);
|
|
2972
3221
|
let commands = [];
|
|
2973
|
-
const textCommand = this.context.generator.text(text, finalX, finalY, finalFont, finalFontSize);
|
|
3222
|
+
const textCommand = this.context.generator.text(text, finalX, finalY, finalFont, finalFontSize, this.rotation);
|
|
2974
3223
|
if (features.length == 0) {
|
|
2975
3224
|
return textCommand;
|
|
2976
3225
|
} else {
|
|
@@ -2987,13 +3236,28 @@ var Text = class extends LabelField {
|
|
|
2987
3236
|
return this.context.generator.commandGroup(commands);
|
|
2988
3237
|
}
|
|
2989
3238
|
textLineCommand(width, x, y, lineHeight, linePercentage, fontSize) {
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
3239
|
+
const offset = Math.round(fontSize * linePercentage - lineHeight / 2);
|
|
3240
|
+
let start;
|
|
3241
|
+
let end;
|
|
3242
|
+
switch (this.rotation) {
|
|
3243
|
+
case 0:
|
|
3244
|
+
start = { x: Math.round(x), y: Math.round(y) + offset };
|
|
3245
|
+
end = { x: Math.round(x) + Math.round(width), y: start.y };
|
|
3246
|
+
break;
|
|
3247
|
+
case 90:
|
|
3248
|
+
start = { x: Math.round(x) - offset, y: Math.round(y) };
|
|
3249
|
+
end = { x: start.x, y: Math.round(y) + Math.round(width) };
|
|
3250
|
+
break;
|
|
3251
|
+
case 180:
|
|
3252
|
+
start = { x: Math.round(x), y: Math.round(y) - offset };
|
|
3253
|
+
end = { x: Math.round(x) - Math.round(width), y: start.y };
|
|
3254
|
+
break;
|
|
3255
|
+
case 270:
|
|
3256
|
+
start = { x: Math.round(x) + offset, y: Math.round(y) };
|
|
3257
|
+
end = { x: start.x, y: Math.round(y) - Math.round(width) };
|
|
3258
|
+
break;
|
|
3259
|
+
}
|
|
3260
|
+
return this.context.generator.line(start, end, lineHeight);
|
|
2997
3261
|
}
|
|
2998
3262
|
getFontName(font) {
|
|
2999
3263
|
var _a;
|
|
@@ -3007,22 +3271,25 @@ var Text = class extends LabelField {
|
|
|
3007
3271
|
get textWidthFunction() {
|
|
3008
3272
|
var _a, _b, _c;
|
|
3009
3273
|
if (this.font.name == "default") {
|
|
3010
|
-
return this.defaultTextWidth;
|
|
3274
|
+
return (text, font) => this.defaultTextWidth(text, font);
|
|
3011
3275
|
} else {
|
|
3012
|
-
return (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.textWidth) != null ? _c : this.defaultTextWidth;
|
|
3276
|
+
return (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.textWidth) != null ? _c : (text, font) => this.defaultTextWidth(text, font);
|
|
3013
3277
|
}
|
|
3014
3278
|
}
|
|
3015
3279
|
/**
|
|
3016
|
-
*
|
|
3017
|
-
*
|
|
3280
|
+
* Fallback width estimate when no font metrics are available.
|
|
3281
|
+
* Uses the TSPL x-multiplication value (dotToPoint of the dot size) as
|
|
3282
|
+
* the per-character width, which matches the rendered width of font "0".
|
|
3018
3283
|
*/
|
|
3019
3284
|
defaultTextWidth(text, font) {
|
|
3020
|
-
|
|
3285
|
+
var _a, _b, _c;
|
|
3286
|
+
const dpi = (_c = (_b = (_a = this.context) == null ? void 0 : _a.config) == null ? void 0 : _b.dpi) != null ? _c : 203;
|
|
3287
|
+
return text.length * dotToPoint(font.size, dpi);
|
|
3021
3288
|
}
|
|
3022
3289
|
};
|
|
3023
3290
|
|
|
3024
3291
|
// src/labels/fields/BarCode.ts
|
|
3025
|
-
var BarCode = class extends
|
|
3292
|
+
var BarCode = class extends RotatableLabelField {
|
|
3026
3293
|
/**
|
|
3027
3294
|
* @param content Content to encode
|
|
3028
3295
|
* @param x X coordinate in dots
|
|
@@ -3040,16 +3307,19 @@ var BarCode = class extends LabelField {
|
|
|
3040
3307
|
this.type = type;
|
|
3041
3308
|
this.height = height;
|
|
3042
3309
|
this.barWidth = barWidth;
|
|
3043
|
-
this.rotation = 0;
|
|
3044
3310
|
this.humanReadable = "none";
|
|
3045
3311
|
this.alignment = "left";
|
|
3046
3312
|
}
|
|
3047
|
-
setRotation(rotation) {
|
|
3048
|
-
this.rotation = rotation;
|
|
3049
|
-
}
|
|
3050
3313
|
setHumanReadable(humanReadable) {
|
|
3051
3314
|
this.humanReadable = humanReadable;
|
|
3052
3315
|
}
|
|
3316
|
+
setPosition(position) {
|
|
3317
|
+
this.x = position.x;
|
|
3318
|
+
this.y = position.y;
|
|
3319
|
+
}
|
|
3320
|
+
getPosition() {
|
|
3321
|
+
return { x: this.x, y: this.y };
|
|
3322
|
+
}
|
|
3053
3323
|
commandForLanguage(language, _config) {
|
|
3054
3324
|
return __async(this, null, function* () {
|
|
3055
3325
|
return yield this.commandGeneratorFor(language).barCode(this.content, this.x, this.y, this.type, this.height, this.rotation, this.humanReadable, this.alignment, this.barWidth);
|
|
@@ -3058,16 +3328,43 @@ var BarCode = class extends LabelField {
|
|
|
3058
3328
|
};
|
|
3059
3329
|
|
|
3060
3330
|
// src/labels/fields/Image.ts
|
|
3061
|
-
var Image2 = class _Image extends
|
|
3331
|
+
var Image2 = class _Image extends RotatableLabelField {
|
|
3062
3332
|
constructor(x, y, image2) {
|
|
3063
3333
|
super();
|
|
3064
3334
|
this.x = x;
|
|
3065
3335
|
this.y = y;
|
|
3066
3336
|
this.image = image2;
|
|
3067
3337
|
}
|
|
3338
|
+
setPosition(position) {
|
|
3339
|
+
this.x = position.x;
|
|
3340
|
+
this.y = position.y;
|
|
3341
|
+
}
|
|
3342
|
+
getPosition() {
|
|
3343
|
+
return { x: this.x, y: this.y };
|
|
3344
|
+
}
|
|
3068
3345
|
commandForLanguage(language, _config) {
|
|
3069
3346
|
return __async(this, null, function* () {
|
|
3070
|
-
|
|
3347
|
+
if (this.rotation === 0) {
|
|
3348
|
+
return yield this.commandGeneratorFor(language).image(this.image, this.x, this.y);
|
|
3349
|
+
}
|
|
3350
|
+
const srcW = this.image.width * 8;
|
|
3351
|
+
const srcH = this.image.height;
|
|
3352
|
+
const bitmap2 = ImageUtils.rotateBWBitmap(this.image, 360 - this.rotation);
|
|
3353
|
+
let dx = this.x;
|
|
3354
|
+
let dy = this.y;
|
|
3355
|
+
switch (this.rotation) {
|
|
3356
|
+
case 90:
|
|
3357
|
+
dx = this.x - srcH;
|
|
3358
|
+
break;
|
|
3359
|
+
case 180:
|
|
3360
|
+
dx = this.x - srcW;
|
|
3361
|
+
dy = this.y - srcH;
|
|
3362
|
+
break;
|
|
3363
|
+
case 270:
|
|
3364
|
+
dy = this.y - srcW;
|
|
3365
|
+
break;
|
|
3366
|
+
}
|
|
3367
|
+
return yield this.commandGeneratorFor(language).image(bitmap2, dx, dy);
|
|
3071
3368
|
});
|
|
3072
3369
|
}
|
|
3073
3370
|
/**
|
|
@@ -3088,7 +3385,7 @@ var Image2 = class _Image extends LabelField {
|
|
|
3088
3385
|
};
|
|
3089
3386
|
|
|
3090
3387
|
// src/labels/fields/QRCode.ts
|
|
3091
|
-
var QRCode = class extends
|
|
3388
|
+
var QRCode = class extends RotatableLabelField {
|
|
3092
3389
|
constructor(content, x, y, width) {
|
|
3093
3390
|
super();
|
|
3094
3391
|
this.content = content;
|
|
@@ -3096,9 +3393,16 @@ var QRCode = class extends LabelField {
|
|
|
3096
3393
|
this.y = y;
|
|
3097
3394
|
this.width = width;
|
|
3098
3395
|
}
|
|
3396
|
+
setPosition(position) {
|
|
3397
|
+
this.x = position.x;
|
|
3398
|
+
this.y = position.y;
|
|
3399
|
+
}
|
|
3400
|
+
getPosition() {
|
|
3401
|
+
return { x: this.x, y: this.y };
|
|
3402
|
+
}
|
|
3099
3403
|
commandForLanguage(language, config) {
|
|
3100
3404
|
return __async(this, null, function* () {
|
|
3101
|
-
return yield this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y);
|
|
3405
|
+
return yield this.commandGeneratorFor(language).qrCode(this.content, this.width, this.x, this.y, this.rotation);
|
|
3102
3406
|
});
|
|
3103
3407
|
}
|
|
3104
3408
|
};
|