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; } }