r-util-js/packages/common/src/printer/tsc-plus.js

308 lines
6.5 KiB
JavaScript
Raw Normal View History

2026-03-16 17:58:57 +08:00
import { TSC } from "./tsc.js";
const fontInfoList = [
{
name: "1",
width: 8,
height: 12,
},
{
name: "2",
width: 12,
height: 20,
},
{
name: "3",
width: 16,
height: 24,
},
{
name: "4",
width: 24,
height: 32,
},
{
name: "5",
width: 32,
height: 48,
},
{
name: "6",
width: 14,
height: 19,
},
{
name: "7",
width: 21,
height: 27,
},
{
name: "8",
width: 14,
height: 25,
},
{
name: "9",
width: 9,
height: 17,
},
{
name: "10",
width: 12,
height: 24,
},
{
name: "TSS16.BF2",
width: 16,
height: 16,
},
{
name: "TSS20.BF2",
width: 20,
height: 20,
},
{
name: "TST24.BF2",
width: 24,
height: 24,
},
{
name: "TSS24.BF2",
width: 24,
height: 24,
},
{
name: "K",
width: 24,
height: 24,
},
{
name: "TSS32.BF2",
width: 32,
height: 32,
},
];
export class TSCPlus extends TSC {
static MILLIMETERS_PER_INCH = 25.4;
constructor(data = []) {
super(data);
this.font = "TSS24.BF2";
this.lineHeight = "1.2";
this.dpi = 200;
this.nextX = 0;
this.nextY = 0;
this.widthDot = this.mmToDot(40);
this.heightDot = this.mmToDot(30);
this.paddingTopDot = 0;
this.paddingLeftDot = 0;
this.paddingRightDot = 0;
this.paddingBottomDot = 0;
this.setSizeDot(this.widthDot, this.heightDot);
}
/**
* 设置内边距
* @param {number} paddingTopDot
* @param {number} paddingRightDot
* @param {number} paddingBottomDot
* @param {number} paddingLeftDot
*/
setPadding(paddingTopDot, paddingRightDot, paddingBottomDot, paddingLeftDot) {
this.paddingTopDot = paddingTopDot;
this.paddingRightDot = paddingRightDot;
this.paddingBottomDot = paddingBottomDot;
this.paddingLeftDot = paddingLeftDot;
this.nextX = this.paddingLeftDot;
this.nextY = this.paddingTopDot;
}
mmToDot(mm) {
mm = Number(mm);
return Math.round(this.dpi / TSCPlus.MILLIMETERS_PER_INCH) * mm;
}
setDpi(dpi) {
this.dpi = dpi;
}
setSize(w, h) {
if (/^\d+(\.\d+)? mm$/.test(w)) {
this.widthDot = this.mmToDot(parseInt(w));
this.heightDot = this.mmToDot(parseInt(h));
} else {
this.widthDot = parseInt(w) * this.dpi;
this.heightDot = parseInt(h) * this.dpi;
}
return super.setSize(w, h);
}
setSizeMM(w, h) {
this.widthDot = w * 8;
this.heightDot = h * 8;
return super.setSizeMM(w, h);
}
setSizeDot(w, h) {
return this.setSizeMM(w / 8, h / 8);
}
/**
* 设置字体
* @param {string} font
*/
setFont(font) {
this.font = String(font);
}
/**
* 设置行高
* @param {string|number} lineHeight
*/
setLineHeight(lineHeight) {
this.lineHeight = String(lineHeight);
}
static getLetterWidthDot(font) {
const fontInfo = fontInfoList.find((v) => v.name === font);
return fontInfo.width;
}
static getFontLineHeightDot(font, lineHeight) {
const fontInfo = fontInfoList.find((v) => v.name === font);
if (/^\d+(\.\d+)?dot$/.test(lineHeight)) {
const [, lineHeightDot] = /^(\d+(\.\d+))?dot$/.exec(lineHeight);
return lineHeightDot;
} else if (/^\d+(\.\d+)?$/.test(lineHeight)) {
const [, lineHeightNum] = /^(\d+(\.\d+))?$/.exec(lineHeight);
const lineHeightDot = fontInfo.height * lineHeightNum;
return lineHeightDot;
} else {
throw new Error("无效行高:" + lineHeight);
}
}
/**
* 获取文本宽度点数
* @param {string} text
* @returns {number}
*/
static getTextDots(text, letterDots = 12) {
text = String(text);
let ch = 0;
text.split("").forEach((c) => {
// 是否是汉字,汉字两倍宽
const isChinese = /[^\x00-\xff]/.test(c);
if (isChinese) {
ch += 2;
} else {
ch++;
}
});
return ch * letterDots;
}
/**
* 根据最大点数获取文本
* @param {string} text
* @param {number} maxDots
* @return {string}
*/
static getMaxText(text = "", maxDots = 0) {
let subStr = "";
for (let i = 0; i < text.length; i++) {
subStr = text.substring(0, text.length - i);
if (TSCPlus.getTextDots(subStr) <= maxDots) {
break;
}
}
return subStr;
}
/**
* 分割字符串
* "123456789" => ["1234", "5678", "9"]
* @param {string} str
* @param {number} maxDots
* @return {string[]}
*/
static splitString(str, maxDots) {
let itemDots = TSCPlus.getTextDots(str);
const arr = [];
while (itemDots > 0) {
const maxStr = TSCPlus.getMaxText(str, maxDots);
arr.push(maxStr);
str = str.slice(maxStr.length);
itemDots = TSCPlus.getTextDots(str);
}
if (str.length > 0) {
arr.push(str);
}
return arr;
}
addTextLn(text, options = {}) {
text = String(text);
const font = String(options.font ?? this.font);
let x = parseInt(options.x ?? this.nextX);
this.nextY = parseInt(options.y ?? this.nextY);
const rotation = parseInt(options.rotation ?? 0);
const sx = parseInt(options.sx ?? 1);
const sy = parseInt(options.sy ?? 1);
const align = options.align ?? "left";
const contentWidth =
this.widthDot - this.paddingLeftDot - this.paddingRightDot;
const textList = TSCPlus.splitString(text, contentWidth);
textList.forEach((t) => {
const textDots = parseInt(TSCPlus.getTextDots(t) * sx);
console.log(align, textDots, contentWidth);
if (textDots < contentWidth) {
if (align == "center") {
x += parseInt((contentWidth - textDots) / 2);
} else if (align == "right") {
x += parseInt(contentWidth - textDots);
}
}
console.log("x", x);
this.setText(x, this.nextY, font, rotation, sx, sy, t);
const lineHeightDot =
TSCPlus.getFontLineHeightDot(font, this.lineHeight) * sy;
this.nextY = parseInt(this.nextY + lineHeightDot);
console.log("this.nextY", this.nextY);
});
return this;
}
addAddBarCode(content, options = {}) {
const x = parseInt(options.x ?? this.nextX);
this.nextY = parseInt(options.y ?? this.nextY);
const height = parseInt(options.height ?? 80);
const rotation = parseInt(options.rotation ?? 0);
this.setBarCode(
x,
this.nextY,
options.codeType,
height,
options.readable,
rotation,
options.narrow,
options.wide,
content,
);
this.nextY += height + 24;
return this;
}
}