@nuintun/qrcode
Version:
A pure JavaScript QRCode encode and decode library.
80 lines (76 loc) • 3.23 kB
JavaScript
/**
* @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 };