quadqr-js 1.4.2 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Versions 2..40 use the same alignment-pattern center schedule as standard
5
5
  * QR Code matrices. QuadQR remains its own symbology, but reuses that proven
6
- * spatial distribution for alignment references. QuadQR uses one 5x5 primary
7
- * alignment reference at the bottom-right and compact 3x3 secondary markers.
6
+ * spatial distribution for alignment references. QuadQR format v6 uses the same
7
+ * proven 5x5 nested alignment marker shape at every scheduled alignment center.
8
+ * Legacy format v5 used one 5x5 primary marker plus compact 3x3 secondaries.
8
9
  * Version 1 keeps the legacy QuadQR bottom-right bootstrap marker because standard QR v1 has no
9
10
  * alignment pattern and the QuadQR camera scanner needs a fourth projective
10
11
  * reference point.
@@ -13,6 +14,14 @@
13
14
  export const MIN_GEOMETRY_VERSION = 1;
14
15
  export const MAX_GEOMETRY_VERSION = 40;
15
16
 
17
+ export const ALIGNMENT_PROFILE_STANDARD_5 = "standard5";
18
+ export const ALIGNMENT_PROFILE_LEGACY_3 = "compact3";
19
+
20
+ export function normalizeAlignmentProfile(profile = ALIGNMENT_PROFILE_STANDARD_5) {
21
+ if (profile === ALIGNMENT_PROFILE_STANDARD_5 || profile === ALIGNMENT_PROFILE_LEGACY_3) return profile;
22
+ throw new Error(`Unsupported alignment profile ${profile}.`);
23
+ }
24
+
16
25
  // Index by version. Entry 0 is unused. Values are module indices of alignment
17
26
  // pattern centers, matching the standard QR Code version layout for v2..v40.
18
27
  export const ALIGNMENT_PATTERN_AXES = Object.freeze([
@@ -79,9 +88,11 @@ export function versionFromSize(size) {
79
88
  : null;
80
89
  }
81
90
 
82
- export function alignmentPatternCentersForVersion(version) {
91
+ export function alignmentPatternCentersForVersion(version, options = {}) {
83
92
  assertVersion(version);
84
93
  const size = sizeForVersion(version);
94
+ const requestedProfile = typeof options === "string" ? options : options.profile;
95
+ const profile = normalizeAlignmentProfile(requestedProfile ?? ALIGNMENT_PROFILE_STANDARD_5);
85
96
 
86
97
  if (version === 1) {
87
98
  const center = size - 4;
@@ -91,7 +102,8 @@ export function alignmentPatternCentersForVersion(version) {
91
102
  size: 5,
92
103
  primary: true,
93
104
  bootstrap: true,
94
- separator: true
105
+ separator: true,
106
+ profile
95
107
  }];
96
108
  }
97
109
 
@@ -113,10 +125,13 @@ export function alignmentPatternCentersForVersion(version) {
113
125
  centers.push({
114
126
  row,
115
127
  col,
116
- size: primary ? 5 : 3,
128
+ // Format v6 uses a real QR-style 5x5 black/white/black alignment eye
129
+ // everywhere. Legacy v5 kept compact 3x3 secondaries to save cells.
130
+ size: profile === ALIGNMENT_PROFILE_LEGACY_3 && !primary ? 3 : 5,
117
131
  primary,
118
132
  bootstrap: false,
119
- separator: false
133
+ separator: false,
134
+ profile
120
135
  });
121
136
  }
122
137
  }
@@ -124,8 +139,8 @@ export function alignmentPatternCentersForVersion(version) {
124
139
  return centers;
125
140
  }
126
141
 
127
- export function primaryAlignmentPatternForVersion(version) {
128
- const centers = alignmentPatternCentersForVersion(version);
142
+ export function primaryAlignmentPatternForVersion(version, options = {}) {
143
+ const centers = alignmentPatternCentersForVersion(version, options);
129
144
  return centers.find((pattern) => pattern.primary) ?? centers[centers.length - 1];
130
145
  }
131
146
 
@@ -138,11 +153,11 @@ export function alignmentPatternIsBlack(pattern, rowOffset, colOffset) {
138
153
  if (Math.abs(rowOffset) > radius || Math.abs(colOffset) > radius) return null;
139
154
 
140
155
  if (pattern.size === 3) {
141
- // Compact secondary marker: black 3x3 ring with a white center.
156
+ // Legacy format-v5 secondary marker: black 3x3 ring with a white center.
142
157
  return rowOffset !== 0 || colOffset !== 0;
143
158
  }
144
159
 
145
- // Primary 5x5 marker: black outer ring, white inner ring, black center.
160
+ // QR-style 5x5 marker: black outer ring, white inner ring, black center.
146
161
  const outer = Math.abs(rowOffset) === 2 || Math.abs(colOffset) === 2;
147
162
  const center = rowOffset === 0 && colOffset === 0;
148
163
  return outer || center;