Skip to content

Commit

Permalink
feat: add qrcode v2
Browse files Browse the repository at this point in the history
  • Loading branch information
Dafnik committed Nov 18, 2024
1 parent 518c977 commit b087c87
Show file tree
Hide file tree
Showing 16 changed files with 492 additions and 231 deletions.
13 changes: 13 additions & 0 deletions libs/dfts-qrcode/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ export type QRCodeMode = 'numeric' | 'alphanumeric' | 'octet';

export type ColorValueHex = `#${string}`;

export type QRCodeOptions = {
version?: QRCodeVersion;
errorCorrectionLevel?: QRCodeErrorCorrectionLevel;
mask?: number;
margin?: number;
scale?: number;
width?: number;
colors?: {
light?: ColorValueHex;
dark?: ColorValueHex;
};
};

export type generateMatrixOptions = {
version?: QRCodeVersion;
mode?: QRCodeMode;
Expand Down
2 changes: 1 addition & 1 deletion libs/dfts-qrcode/src/lib/v2/core/abstract-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Mode } from './mode';
import { BitBuffer } from './bit-buffer';

export abstract class AbstractData {
protected constructor(protected mode: Mode) {}
protected constructor(public mode: Mode) {}

abstract getLength(): number;

Expand Down
2 changes: 1 addition & 1 deletion libs/dfts-qrcode/src/lib/v2/core/bit-buffer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export class BitBuffer {
constructor(
private buffer: number[],
public buffer: number[] = [],
private length = 0,
) {}

Expand Down
2 changes: 1 addition & 1 deletion libs/dfts-qrcode/src/lib/v2/core/bit-matrix.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type BitType = 0 | 1;
export type BitType = 0 | 1;

export class BitMatrix {
public readonly data: Uint8Array;
Expand Down
130 changes: 64 additions & 66 deletions libs/dfts-qrcode/src/lib/v2/core/dijkstra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,75 +144,73 @@ class PriorityQueue {
}
}

export const dijkstra = {
single_source_shortest_paths: function (
graph: { [nodeID: string]: { [neighborID: string]: number } },
s: string,
d?: string,
): { [nodeID: string]: string } {
const predecessors: { [nodeID: string]: string } = {};
const costs: { [nodeID: string]: number } = {};
costs[s] = 0;

const open = new PriorityQueue();
open.push(s, 0);

let closest: { value: string; cost: number };
let u: string;
let v: string;
let cost_of_s_to_u: number;
let adjacent_nodes: { [neighborID: string]: number };
let cost_of_e: number;
let cost_of_s_to_u_plus_cost_of_e: number;
let cost_of_s_to_v: number | undefined;
let first_visit: boolean;

while (!open.empty()) {
closest = open.pop();
u = closest.value;
cost_of_s_to_u = closest.cost;

adjacent_nodes = graph[u] || {};

for (v in adjacent_nodes) {
// eslint-disable-next-line no-prototype-builtins
if (adjacent_nodes.hasOwnProperty(v)) {
cost_of_e = adjacent_nodes[v];
cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;

cost_of_s_to_v = costs[v];
first_visit = typeof cost_of_s_to_v === 'undefined';

if (first_visit || cost_of_s_to_v! > cost_of_s_to_u_plus_cost_of_e) {
costs[v] = cost_of_s_to_u_plus_cost_of_e;
open.push(v, cost_of_s_to_u_plus_cost_of_e);
predecessors[v] = u;
}
export function dijkstra_singleSourceShortestPaths(
graph: { [nodeID: string]: { [neighborID: string]: number } },
s: string,
d?: string,
): { [nodeID: string]: string } {
const predecessors: { [nodeID: string]: string } = {};
const costs: { [nodeID: string]: number } = {};
costs[s] = 0;

const open = new PriorityQueue();
open.push(s, 0);

let closest: { value: string; cost: number };
let u: string;
let v: string;
let cost_of_s_to_u: number;
let adjacent_nodes: { [neighborID: string]: number };
let cost_of_e: number;
let cost_of_s_to_u_plus_cost_of_e: number;
let cost_of_s_to_v: number | undefined;
let first_visit: boolean;

while (!open.empty()) {
closest = open.pop();
u = closest.value;
cost_of_s_to_u = closest.cost;

adjacent_nodes = graph[u] || {};

for (v in adjacent_nodes) {
// eslint-disable-next-line no-prototype-builtins
if (adjacent_nodes.hasOwnProperty(v)) {
cost_of_e = adjacent_nodes[v];
cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;

cost_of_s_to_v = costs[v];
first_visit = typeof cost_of_s_to_v === 'undefined';

if (first_visit || cost_of_s_to_v! > cost_of_s_to_u_plus_cost_of_e) {
costs[v] = cost_of_s_to_u_plus_cost_of_e;
open.push(v, cost_of_s_to_u_plus_cost_of_e);
predecessors[v] = u;
}
}
}
}

if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {
const msg = `Could not find a path from ${s} to ${d}.`;
throw new Error(msg);
}
if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {
const msg = `Could not find a path from ${s} to ${d}.`;
throw new Error(msg);
}

return predecessors;
},
return predecessors;
}

extract_shortest_path_from_predecessor_list: function (predecessors: { [nodeID: string]: string }, d: string): string[] {
const nodes: string[] = [];
let u: string | undefined = d;
while (u) {
nodes.push(u);
u = predecessors[u];
}
nodes.reverse();
return nodes;
},

find_path: function (graph: { [nodeID: string]: { [neighborID: string]: number } }, s: string, d: string): string[] {
const predecessors = this.single_source_shortest_paths(graph, s, d);
return this.extract_shortest_path_from_predecessor_list(predecessors, d);
},
};
export function dijkstra_extractShortestPathFromPredecessorList(predecessors: { [nodeID: string]: string }, d: string): string[] {
const nodes: string[] = [];
let u: string | undefined = d;
while (u) {
nodes.push(u);
u = predecessors[u];
}
nodes.reverse();
return nodes;
}

export function dijkstra_findPath(graph: { [nodeID: string]: { [neighborID: string]: number } }, s: string, d: string): string[] {
const predecessors = dijkstra_singleSourceShortestPaths(graph, s, d);
return dijkstra_extractShortestPathFromPredecessorList(predecessors, d);
}
8 changes: 4 additions & 4 deletions libs/dfts-qrcode/src/lib/v2/core/error-correction-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const EC_CODEWORDS_TABLE = [
* @param {Number} errorCorrectionLevel Error correction level
* @return {Number} Number of error correction blocks
*/
export function getBlocksCount(version: number, errorCorrectionLevel: ErrorCorrectionLevel): number | undefined {
export function getBlocksCount(version: number, errorCorrectionLevel: ErrorCorrectionLevel): number {
switch (errorCorrectionLevel) {
case L:
// noinspection PointlessArithmeticExpressionJS
Expand All @@ -39,7 +39,7 @@ export function getBlocksCount(version: number, errorCorrectionLevel: ErrorCorre
case H:
return EC_BLOCKS_TABLE[(version - 1) * 4 + 3];
default:
return undefined;
throw Error(`Unknown error correction level ${errorCorrectionLevel.bit}`);
}
}

Expand All @@ -51,7 +51,7 @@ export function getBlocksCount(version: number, errorCorrectionLevel: ErrorCorre
* @param {Number} errorCorrectionLevel Error correction level
* @return {Number} Number of error correction codewords
*/
export function getTotalCodewordsCount(version: number, errorCorrectionLevel: ErrorCorrectionLevel): number | undefined {
export function getTotalCodewordsCount(version: number, errorCorrectionLevel: ErrorCorrectionLevel): number {
switch (errorCorrectionLevel) {
case L:
// noinspection PointlessArithmeticExpressionJS
Expand All @@ -63,6 +63,6 @@ export function getTotalCodewordsCount(version: number, errorCorrectionLevel: Er
case H:
return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3];
default:
return undefined;
throw Error(`Unknown error correction level ${errorCorrectionLevel.bit}`);
}
}
5 changes: 4 additions & 1 deletion libs/dfts-qrcode/src/lib/v2/core/error-correction-level.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export function isValidErrorCorrectionLevel(level: ErrorCorrectionLevel | string
return !!level && typeof level !== 'string' && level.bit >= 0 && level.bit < 4;
}

export function from(value: ErrorCorrectionLevel | string | undefined | null, defaultValue: ErrorCorrectionLevel): ErrorCorrectionLevel {
export function fromErrorCorrectionLevel(
value: ErrorCorrectionLevel | string | undefined | null,
defaultValue: ErrorCorrectionLevel,
): ErrorCorrectionLevel {
if (isValidErrorCorrectionLevel(value)) {
return value;
}
Expand Down
8 changes: 4 additions & 4 deletions libs/dfts-qrcode/src/lib/v2/core/mask-pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export function isValidMask(mask: number): boolean {
* @param {Number|String} value Mask pattern value
* @return {Number} Valid mask pattern or undefined
*/
export function toMask(value: number): number | undefined {
return isValidMask(value) ? value : undefined;
export function toMask(value: number | undefined): number | undefined {
return value ? (isValidMask(value) ? value : undefined) : undefined;
}

/**
Expand Down Expand Up @@ -196,7 +196,7 @@ function getMaskAt(maskPattern: number, i: number, j: number): boolean {
* @param {Number} pattern Pattern reference number
* @param {BitMatrix} data BitMatrix data
*/
export function applyMask(pattern: number, data: BitMatrix) {
export function applyMask(pattern: number, data: BitMatrix): void {
const size = data.size;

for (let col = 0; col < size; col++) {
Expand All @@ -214,7 +214,7 @@ export function applyMask(pattern: number, data: BitMatrix) {
* @param setupFormatFunc
* @return {Number} Mask pattern reference number
*/
export function getBestMask(data: BitMatrix, setupFormatFunc: (p: number) => void) {
export function getBestMask(data: BitMatrix, setupFormatFunc: (p: number) => void): number {
const numPatterns = Object.keys(exports.Patterns).length;
let bestPattern = 0;
let lowerPenalty = Infinity;
Expand Down
2 changes: 1 addition & 1 deletion libs/dfts-qrcode/src/lib/v2/core/numeric-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { NUMERIC } from './mode';
export class NumericData extends AbstractData {
private readonly data: string;

constructor(data: number) {
constructor(data: string) {
super(NUMERIC);

this.data = data.toString();
Expand Down
Loading

0 comments on commit b087c87

Please sign in to comment.