UNPKG

@nuintun/qrcode

Version:

A pure JavaScript QRCode encode and decode library.

83 lines (78 loc) 3.41 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 */ 'use strict'; const Point = require('../../common/Point.cjs'); const utils = require('../../common/utils.cjs'); const Pattern = require('../Pattern.cjs'); const PlotLine = require('../../common/PlotLine.cjs'); const FinderPatternGroup = require('../FinderPatternGroup.cjs'); /** * @module timing */ function calculateEstimateTimingRatio(axis, control) { return control > axis ? 1 : control < axis ? -1 : 0; } function getEstimateTimingPointXAxis(pattern, ratio) { const [left, , right] = Pattern.Pattern.rect(pattern); return ratio > 0 ? right : ratio < 0 ? left : pattern.x; } function getEstimateTimingPointYAxis(pattern, ratio) { const [, top, , bottom] = Pattern.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.Point(startXTranslate, startYTranslate), new Point.Point(endXTranslate, endYTranslate)]; } if (isVertical ? xRatio === yRatio : xRatio !== yRatio) { return [new Point.Point(startX, startYTranslate), new Point.Point(endX, endYTranslate)]; } return [new Point.Point(startXTranslate, startY), new Point.Point(endXTranslate, endY)]; } function isValidTimingLine(matrix, start, end, size) { const maxModules = size + 8; const points = new PlotLine.PlotLine(start, end).points(); let modules = 1; let lastBit = matrix.get(utils.toInt32(start.x), utils.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.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.Point(startX, startY), new Point.Point(endX, endY), size); } exports.checkEstimateTimingLine = checkEstimateTimingLine; exports.checkMappingTimingLine = checkMappingTimingLine;