UNPKG

@nuintun/qrcode

Version:

A pure JavaScript QRCode encode and decode library.

80 lines (76 loc) 3.23 kB
/** * @module QRCode * @package @nuintun/qrcode * @license MIT * @version 5.0.2 * @author nuintun <nuintun@qq.com> * @description A pure JavaScript QRCode encode and decode library. * @see https://github.com/nuintun/qrcode#readme */ import { Point } from '../../common/Point.js'; import { toInt32 } from '../../common/utils.js'; import { Pattern } from '../Pattern.js'; import { PlotLine } from '../../common/PlotLine.js'; import { FinderPatternGroup } from '../FinderPatternGroup.js'; /** * @module timing */ function calculateEstimateTimingRatio(axis, control) { return control > axis ? 1 : control < axis ? -1 : 0; } function getEstimateTimingPointXAxis(pattern, ratio) { const [left, , right] = Pattern.rect(pattern); return ratio > 0 ? right : ratio < 0 ? left : pattern.x; } function getEstimateTimingPointYAxis(pattern, ratio) { const [, top, , bottom] = Pattern.rect(pattern); return ratio > 0 ? bottom : ratio < 0 ? top : pattern.y; } function getEstimateTimingLine(start, end, control, isVertical) { const { x: endX, y: endY } = end; const { x: startX, y: startY } = start; const { x: controlX, y: controlY } = control; const xRatio = calculateEstimateTimingRatio(endX, controlX); const yRatio = calculateEstimateTimingRatio(endY, controlY); const endXTranslate = getEstimateTimingPointXAxis(end, xRatio); const endYTranslate = getEstimateTimingPointYAxis(end, yRatio); const startXTranslate = getEstimateTimingPointXAxis(start, xRatio); const startYTranslate = getEstimateTimingPointYAxis(start, yRatio); if (xRatio === 0 || yRatio === 0) { return [new Point(startXTranslate, startYTranslate), new Point(endXTranslate, endYTranslate)]; } if (isVertical ? xRatio === yRatio : xRatio !== yRatio) { return [new Point(startX, startYTranslate), new Point(endX, endYTranslate)]; } return [new Point(startXTranslate, startY), new Point(endXTranslate, endY)]; } function isValidTimingLine(matrix, start, end, size) { const maxModules = size + 8; const points = new PlotLine(start, end).points(); let modules = 1; let lastBit = matrix.get(toInt32(start.x), toInt32(start.y)); for (const [x, y] of points) { const bit = matrix.get(x, y); if (bit !== lastBit) { modules++; lastBit = bit; if (modules > maxModules) { return false; } } } return modules >= size - 14 - Math.max(2, (size - 17) / 4); } function checkEstimateTimingLine(matrix, finderPatternGroup, isVertical) { const { topLeft, topRight, bottomLeft } = finderPatternGroup; const [start, end] = isVertical ? getEstimateTimingLine(topLeft, bottomLeft, topRight, true) : getEstimateTimingLine(topLeft, topRight, bottomLeft); return isValidTimingLine(matrix, start, end, FinderPatternGroup.size(finderPatternGroup)); } function checkMappingTimingLine(matrix, transform, size, isVertical) { const [startX, startY] = transform.mapping(isVertical ? 6.5 : 7.5, isVertical ? 7.5 : 6.5); const [endX, endY] = transform.mapping(isVertical ? 6.5 : size - 7.5, isVertical ? size - 7.5 : 6.5); return isValidTimingLine(matrix, new Point(startX, startY), new Point(endX, endY), size); } export { checkEstimateTimingLine, checkMappingTimingLine };