<template>
	<view>
		<canvas canvas-id="reusableCanvas" :width="currentCanvasWidth" :height="currentCanvasHeight"
			class="offscreen-canvas"></canvas>
	</view>
</template>

<script>
	export default {
		name: "textToDotMatrixFor7305",
		props: {
			txts: {
				type: Array,
				default: () => [],
				validator: (value) => value.every(item => typeof item === 'string')
			},
			
			fontSize: {
				type: Number,
				default: 16,
				validator: (value) => value > 0 && value <= 100
			},
			bgColor: {
				type: String,
				default: "#ffffff"
			},
			color: {
				type: String,
				default: "#000000"
			}
		},
		data() {
			return {
				// 当前Canvas的宽高（动态调整）
				currentCanvasWidth: 0,
				currentCanvasHeight: 0,
				// Canvas上下文（复用）
				ctx: null
			};
		},
		computed: {
			validTxts() {
				return this.txts.filter(line => line.trim() !== '');
			}
		},
		mounted() {
			// 初始化Canvas上下文（只创建一次）
			this.ctx = uni.createCanvasContext('reusableCanvas', this);
		},
		methods: {
			/**
			 * 估算单行文本所需的Canvas宽度
			 */
			calcLineWidth(textLine) {
				return textLine.length * this.fontSize;
			},

			/**
			 * 清除Canvas内容
			 */
			clearCanvas() {
				// 先清除，再用背景色填充，确保无残留
				this.ctx.clearRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight);
				this.ctx.setFillStyle(this.bgColor);
				this.ctx.fillRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight);
			},

			/**
			 * 复用单个Canvas处理所有文本行
			 */
			async drawAndGetPixels() {
				// 超采样比例（提高分辨率再降采样，减少模糊）
				const SCALE = 3;
				const PADDING_X = 1 * SCALE; // 左侧预留像素，避免首字裁剪
				let binaryToHex = (binaryArray) => {
					if (!Array.isArray(binaryArray) || binaryArray.length !== 8) {
						throw new Error("输入必须是包含8个元素的二进制数组");
					}

					// 检查每个元素是否为0或1
					if (!binaryArray.every(bit => bit === 0 || bit === 1)) {
						throw new Error("数组元素必须只能是0或1");
					}

					// 将二进制数组转换为十进制数
					let decimalValue = 0;
					for (let i = 0; i < 8; i++) {
						// 计算每个位的权重并累加
						decimalValue += binaryArray[i] * Math.pow(2, 7 - i);
					}

					// 将十进制转换为十六进制字符串，并添加0x前缀
					const hexString = "0x" + decimalValue.toString(16).padStart(2, '0').toUpperCase();

					return hexString;
				}

				let convertCharToMatrix = (drawResult, item) => {
					// 设备端使用13x13点阵渲染
					const charWidth = 13;
					const charHeight = 13;
					const { pixelData, width, height } = drawResult;
					// 将高分辨率像素降采样为13x13的布尔矩阵
					const target = new Array(charWidth * charHeight).fill(0);
					const threshold = 0.5; // 每个小块中超过50%亮色（文字）判为1
					
					// 确保采样区域严格对齐，从PADDING_X开始，只采样13列
					// 字符实际绘制区域：从PADDING_X开始，宽度为13*SCALE
					const charStartX = PADDING_X;
					const charEndX = PADDING_X + charWidth * SCALE;
					
					for (let y = 0; y < charHeight; y++) {
						for (let x = 0; x < charWidth; x++) {
							let onCount = 0;
							let total = 0;
							// 采样区域：字符从PADDING_X开始绘制，每列宽度为SCALE
							const startX = PADDING_X + x * SCALE;
							const startY = y * SCALE;
							
							for (let sy = 0; sy < SCALE; sy++) {
								for (let sx = 0; sx < SCALE; sx++) {
									const px = startX + sx;
									const py = startY + sy;
									
									// 边界检查：确保不超出Canvas边界，且不超出字符实际绘制区域
									if (px < 0 || py < 0 || px >= width || py >= height) {
										// 边界外视为背景（黑色）
										continue;
									}
									// 额外检查：确保不采样到字符右侧的残留区域
									if (px >= charEndX) {
										// 超出字符区域，视为背景
										continue;
									}
									
									const idx = (py * width + px) * 4;
									const R = pixelData[idx];
									const G = pixelData[idx + 1];
									const B = pixelData[idx + 2];
									const A = pixelData[idx + 3] || 255;
									// 计算亮度
									const luminance = 0.299 * R + 0.587 * G + 0.114 * B;
									const alpha = A / 255;
									// 背景是黑色，文字是白色，所以判断亮色（>=128）为文字点
									if (luminance >= 128 && alpha > 0.5) onCount++;
									total++;
								}
							}
							// 当亮色占比超过阈值时判为1（至少需要采样到一些像素）
							target[y * charWidth + x] = (total > 0 && onCount / total >= threshold) ? 1 : 0;
						}
					}

					const lowBytes = new Array(charWidth).fill(0);
					const highBytes = new Array(charWidth).fill(0);
					// 按列打包，每列13行分成上下两字节：低字节0-7行（8行），高字节8-12行（5行）
					for (let col = 0; col < charWidth; col++) {
						for (let row = 0; row < charHeight; row++) {
							const pixel = target[row * charWidth + col];
							if (pixel === 1) {
								if (row < 8) {
									// 低字节：0-7行，从低位到高位
									lowBytes[col] |= (1 << row);
								} else {
									// 高字节：8-12行，从低位到高位（使用5位，剩余3位未使用）
									highBytes[col] |= (1 << (row - 8));
								}
							}
						}
					}
					return [...lowBytes, ...highBytes];
				}

				let drawTxt = async (textLine) => {
					let result = {};
					let ctx = this.ctx;

					// 1. 动态调整Canvas尺寸（高分辨率）
					// 设备端使用13x13点阵渲染
					this.currentCanvasWidth = 13 * SCALE + PADDING_X;
					this.currentCanvasHeight = 13 * SCALE;

					// 2. 清空Canvas（绘制背景）
					this.clearCanvas();

					// 3. 设置文字样式（整数像素对齐，顶部基线，避免首字裁剪）
					ctx.setFillStyle(this.color);
					ctx.setTextBaseline('top');
					ctx.setTextAlign('left');
					const fs = Math.max(1, Math.round(this.fontSize)) * SCALE;
					ctx.setFontSize(fs);
					ctx.font = `${fs}px "PingFangBold", "PingFang SC", Arial, sans-serif`;

					// 4. 绘制单个字符（每个字符独立绘制在固定位置）
					// 确保字符始终从PADDING_X开始绘制，Y坐标为0，保证采样一致性
					const charX = PADDING_X;
					const charY = 0;
					ctx.fillText(textLine, charX, charY);

					// 5. 异步绘制并获取像素数据（串行处理避免冲突）
					await new Promise((resolve, reject) => {
						ctx.draw(false, () => {
							uni.canvasGetImageData({
								canvasId: 'reusableCanvas',
								x: 0,
								y: 0,
								width: this.currentCanvasWidth,
								height: this.currentCanvasHeight,
								success: res => {
								result = {
									line: textLine,
									pixelData: res.data,
									width: this.currentCanvasWidth,
									height: this.currentCanvasHeight
								};
									resolve();
								},
								fail: err => {
									// console.error(`处理第${i+1}行失败:`, err);
									reject(err)
								}
							});
						});
					});

					return result;
				}
				let arr = [];
				// 循环处理每行文本
				for (let i = 0; i < this.validTxts.length; i++) {

					let linePixls = [];
					let item = this.validTxts[i];
					// console.log("item=", item);
					for (var j = 0; j < item.length; j++) {
						let char = item[j];
						let result = await drawTxt(char);
						let matrix = convertCharToMatrix(result, item);
						// 调试：打印每个字符的点阵数据
						console.log(`[点阵生成] 字符"${char}" 点阵数据:`, matrix.map(b => '0x' + b.toString(16).padStart(2, '0')).join(' '));
						linePixls.push(matrix);
					}
					// console.log("hexs=", linePixls.join(","));
					arr.push(linePixls);
				}

				return arr;
			}
		}
	};
</script>

<style>
	.offscreen-canvas {
		position: fixed;
		left: -9999px;
		top: -9999px;
	}
</style>