qreator 9.7.2 → 9.8.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.
Files changed (48) hide show
  1. package/README.md +18 -0
  2. package/lib/browser/pdf.umd.js +159 -64
  3. package/lib/browser/pdf.umd.js.map +1 -1
  4. package/lib/browser/png.d.ts +1 -1
  5. package/lib/browser/png.umd.js +137 -39
  6. package/lib/browser/png.umd.js.map +1 -1
  7. package/lib/browser/png_browser.d.ts +1 -1
  8. package/lib/browser/react.umd.js +183 -79
  9. package/lib/browser/react.umd.js.map +1 -1
  10. package/lib/browser/svg.d.ts +1 -1
  11. package/lib/browser/svg.umd.js +143 -39
  12. package/lib/browser/svg.umd.js.map +1 -1
  13. package/lib/browser/typing/types.d.ts +6 -0
  14. package/lib/browser/utils.d.ts +8 -2
  15. package/lib/errorcode.js +12 -16
  16. package/lib/errorcode.js.map +1 -1
  17. package/lib/matrix.js +11 -3
  18. package/lib/matrix.js.map +1 -1
  19. package/lib/pdf.js +26 -18
  20. package/lib/pdf.js.map +1 -1
  21. package/lib/png.d.ts +1 -1
  22. package/lib/png.js +5 -1
  23. package/lib/png.js.map +1 -1
  24. package/lib/png_browser.d.ts +1 -1
  25. package/lib/png_browser.js +17 -6
  26. package/lib/png_browser.js.map +1 -1
  27. package/lib/qr-base.js +6 -4
  28. package/lib/qr-base.js.map +1 -1
  29. package/lib/svg.d.ts +1 -1
  30. package/lib/svg.js +23 -6
  31. package/lib/svg.js.map +1 -1
  32. package/lib/tests/test.js +73 -1
  33. package/lib/tests/test.js.map +1 -1
  34. package/lib/typing/types.d.ts +6 -0
  35. package/lib/utils.d.ts +8 -2
  36. package/lib/utils.js +92 -11
  37. package/lib/utils.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/errorcode.ts +10 -17
  40. package/src/matrix.ts +13 -3
  41. package/src/pdf.ts +30 -17
  42. package/src/png.ts +8 -0
  43. package/src/png_browser.ts +19 -5
  44. package/src/qr-base.ts +6 -4
  45. package/src/svg.ts +28 -6
  46. package/src/tests/test.ts +73 -1
  47. package/src/typing/types.ts +45 -0
  48. package/src/utils.ts +114 -12
package/README.md CHANGED
@@ -14,6 +14,8 @@ QR Code generator for browser and node.js with tree shaking and logo support
14
14
  - supports color customization
15
15
  - supports logos
16
16
  - supports border-radius
17
+ - supports corner mode (merged rounded corners)
18
+ - supports finder pattern customization (shape + color)
17
19
  - tree shaking support
18
20
  - browser / node.js
19
21
 
@@ -47,6 +49,18 @@ const pngBuffer = await getPNG("I love QR", {
47
49
  });
48
50
  ```
49
51
 
52
+ ### Finder pattern customization
53
+
54
+ ```javascript
55
+ const svgString = await getSVG("I love QR", {
56
+ finderOuterShape: "drop",
57
+ finderInnerShape: "circle",
58
+ finderColor: "#ff0000",
59
+ borderRadius: 2,
60
+ cornerMode: "merge",
61
+ });
62
+ ```
63
+
50
64
  [More examples](./examples)
51
65
 
52
66
  ### Syntax
@@ -75,6 +89,10 @@ const pngBuffer = await getPNG("I love QR", {
75
89
  | `color` | module color in rgba or hex format | number | `#000000` - `#000000` | `#000000`<br />(black with 100% opacity) |
76
90
  | `bgColor` | background color in rgba or hex format | number | `#000000` - `#FFFFFF` | `#FFFFFF`<br />(white with 100% opacity) |
77
91
  | `borderRadius` | border-radius (in pixels) | number | 0 - `size / 2` | `0` |
92
+ | `cornerMode` | how corners are rendered when borderRadius > 0 | string | `individual`, `merge` | `individual` |
93
+ | `finderOuterShape` | shape of the outer ring of finder patterns | string | `square`, `rounded`, `circle`, `drop` | `undefined` |
94
+ | `finderInnerShape` | shape of the inner dot of finder patterns | string | `square`, `rounded`, `circle`, `drop` | `undefined` |
95
+ | `finderColor` | color of finder patterns (overrides `color`) | number/string | same as `color` | `undefined` |
78
96
  | `noExcavate` | don't remove partially covered modules | boolean | `true`, `false` | `false` |
79
97
 
80
98
 
@@ -761,7 +761,7 @@
761
761
  function requireCommon () {
762
762
  if (hasRequiredCommon) return common;
763
763
  hasRequiredCommon = 1;
764
- (function (exports) {
764
+ (function (exports$1) {
765
765
 
766
766
 
767
767
  var TYPED_OK = (typeof Uint8Array !== 'undefined') &&
@@ -772,7 +772,7 @@
772
772
  return Object.prototype.hasOwnProperty.call(obj, key);
773
773
  }
774
774
 
775
- exports.assign = function (obj /*from1, from2, from3, ...*/) {
775
+ exports$1.assign = function (obj /*from1, from2, from3, ...*/) {
776
776
  var sources = Array.prototype.slice.call(arguments, 1);
777
777
  while (sources.length) {
778
778
  var source = sources.shift();
@@ -794,7 +794,7 @@
794
794
 
795
795
 
796
796
  // reduce buffer size, avoiding mem copy
797
- exports.shrinkBuf = function (buf, size) {
797
+ exports$1.shrinkBuf = function (buf, size) {
798
798
  if (buf.length === size) { return buf; }
799
799
  if (buf.subarray) { return buf.subarray(0, size); }
800
800
  buf.length = size;
@@ -851,21 +851,21 @@
851
851
 
852
852
  // Enable/Disable typed arrays use, for testing
853
853
  //
854
- exports.setTyped = function (on) {
854
+ exports$1.setTyped = function (on) {
855
855
  if (on) {
856
- exports.Buf8 = Uint8Array;
857
- exports.Buf16 = Uint16Array;
858
- exports.Buf32 = Int32Array;
859
- exports.assign(exports, fnTyped);
856
+ exports$1.Buf8 = Uint8Array;
857
+ exports$1.Buf16 = Uint16Array;
858
+ exports$1.Buf32 = Int32Array;
859
+ exports$1.assign(exports$1, fnTyped);
860
860
  } else {
861
- exports.Buf8 = Array;
862
- exports.Buf16 = Array;
863
- exports.Buf32 = Array;
864
- exports.assign(exports, fnUntyped);
861
+ exports$1.Buf8 = Array;
862
+ exports$1.Buf16 = Array;
863
+ exports$1.Buf32 = Array;
864
+ exports$1.assign(exports$1, fnUntyped);
865
865
  }
866
866
  };
867
867
 
868
- exports.setTyped(TYPED_OK);
868
+ exports$1.setTyped(TYPED_OK);
869
869
  } (common));
870
870
  return common;
871
871
  }
@@ -25794,22 +25794,22 @@
25794
25794
  }
25795
25795
 
25796
25796
  function calculateEC(msg, ec_len) {
25797
- msg = [].slice.call(msg);
25797
+ const len = msg.length;
25798
+ const buf = new Array(len + ec_len);
25799
+ for (let i = 0; i < len; i++)
25800
+ buf[i] = msg[i];
25801
+ for (let i = len; i < len + ec_len; i++)
25802
+ buf[i] = 0;
25798
25803
  const poly = generatorPolynomial(ec_len);
25799
- for (let i = 0; i < ec_len; i++)
25800
- msg.push(0);
25801
- while (msg.length > ec_len) {
25802
- if (!msg[0]) {
25803
- msg.shift();
25804
+ for (let offset = 0; offset < len; offset++) {
25805
+ if (!buf[offset])
25804
25806
  continue;
25805
- }
25806
- const log_k = log(msg[0]);
25807
+ const log_k = log(buf[offset]);
25807
25808
  for (let i = 0; i <= ec_len; i++) {
25808
- msg[i] = msg[i] ^ exp(poly[i] + log_k);
25809
+ buf[offset + i] = buf[offset + i] ^ exp(poly[i] + log_k);
25809
25810
  }
25810
- msg.shift();
25811
25811
  }
25812
- return new Uint8Array(msg);
25812
+ return new Uint8Array(buf.slice(len));
25813
25813
  }
25814
25814
  const GF256_BASE = 285;
25815
25815
  const EXP_TABLE = [1];
@@ -25824,11 +25824,7 @@
25824
25824
  LOG_TABLE[EXP_TABLE[i]] = i;
25825
25825
  }
25826
25826
  function exp(k) {
25827
- while (k < 0)
25828
- k += 255;
25829
- while (k > 255)
25830
- k -= 255;
25831
- return EXP_TABLE[k];
25827
+ return EXP_TABLE[((k % 255) + 255) % 255];
25832
25828
  }
25833
25829
  function log(k) {
25834
25830
  if (k < 1 || k > 255) {
@@ -26192,9 +26188,17 @@
26192
26188
  bestMask = mask;
26193
26189
  }
26194
26190
  }
26195
- fillData(matrix, data, bestMask);
26196
- fillReserved(matrix, data.ec_level, bestMask);
26197
- return matrix.map((row) => row.map((cell) => (cell & 1)));
26191
+ if (bestMask !== 7) {
26192
+ fillData(matrix, data, bestMask);
26193
+ fillReserved(matrix, data.ec_level, bestMask);
26194
+ }
26195
+ for (let i = 0; i < matrix.length; i++) {
26196
+ const row = matrix[i];
26197
+ for (let j = 0; j < row.length; j++) {
26198
+ row[j] = (row[j] & 1);
26199
+ }
26200
+ }
26201
+ return matrix;
26198
26202
  }
26199
26203
 
26200
26204
  const EC_LEVELS = ["L", "M", "Q", "H"];
@@ -26210,7 +26214,7 @@
26210
26214
  for (; i < 10; i++) {
26211
26215
  let version = mappedVersions[i][ec_level];
26212
26216
  if (version.data_len >= len) {
26213
- return deepCopy(version);
26217
+ return copyTemplate(version);
26214
26218
  }
26215
26219
  }
26216
26220
  if (message.data10) {
@@ -26222,14 +26226,14 @@
26222
26226
  for (; i < 27; i++) {
26223
26227
  let version = mappedVersions[i][ec_level];
26224
26228
  if (version.data_len >= len) {
26225
- return deepCopy(version);
26229
+ return copyTemplate(version);
26226
26230
  }
26227
26231
  }
26228
26232
  len = Math.ceil(message.data27.length / 8);
26229
26233
  for (; i < 41; i++) {
26230
26234
  let version = mappedVersions[i][ec_level];
26231
26235
  if (version.data_len >= len) {
26232
- return deepCopy(version);
26236
+ return copyTemplate(version);
26233
26237
  }
26234
26238
  }
26235
26239
  throw new Error("Too much data");
@@ -26274,7 +26278,9 @@
26274
26278
  const data = fillTemplate(message, getTemplate(message, ec_level));
26275
26279
  return getMatrix(data);
26276
26280
  }
26277
- const deepCopy = typeof structuredClone !== "undefined" ? structuredClone : ((obj) => JSON.parse(JSON.stringify(obj)));
26281
+ function copyTemplate(t) {
26282
+ return { ...t, blocks: [...t.blocks], ec: [] };
26283
+ }
26278
26284
  const versions = [
26279
26285
  [],
26280
26286
  [26, 7, 1, 10, 1, 13, 1, 17, 1],
@@ -26857,7 +26863,22 @@
26857
26863
  }
26858
26864
  return rectangles.join(" ");
26859
26865
  }
26860
- function getDotsSVGPath(matrix, size, margin = 0, borderRadius = 0) {
26866
+ function isActive(matrix, x, y) {
26867
+ return x >= 0 && x < matrix.length && y >= 0 && y < (matrix[0]?.length ?? 0) && !!matrix[x][y];
26868
+ }
26869
+ function getExposedCorners(matrix, x, y) {
26870
+ const left = isActive(matrix, x - 1, y);
26871
+ const right = isActive(matrix, x + 1, y);
26872
+ const top = isActive(matrix, x, y - 1);
26873
+ const bottom = isActive(matrix, x, y + 1);
26874
+ return [
26875
+ !left && !top,
26876
+ !right && !top,
26877
+ !right && !bottom,
26878
+ !left && !bottom,
26879
+ ];
26880
+ }
26881
+ function getDotsSVGPath(matrix, size, margin = 0, borderRadius = 0, cornerMode = 'individual') {
26861
26882
  let rectangles = [];
26862
26883
  for (let x = 0; x < matrix.length; x++) {
26863
26884
  const column = matrix[x];
@@ -26865,17 +26886,27 @@
26865
26886
  if (column[y]) {
26866
26887
  const leftX = x * size + margin;
26867
26888
  const topY = y * size + margin;
26868
- const delta = size - 2 * borderRadius;
26889
+ let rTL, rTR, rBR, rBL;
26890
+ if (cornerMode === 'merge') {
26891
+ const [eTL, eTR, eBR, eBL] = getExposedCorners(matrix, x, y);
26892
+ rTL = eTL ? borderRadius : 0;
26893
+ rTR = eTR ? borderRadius : 0;
26894
+ rBR = eBR ? borderRadius : 0;
26895
+ rBL = eBL ? borderRadius : 0;
26896
+ }
26897
+ else {
26898
+ rTL = rTR = rBR = rBL = borderRadius;
26899
+ }
26869
26900
  const rectangle = [
26870
- svgMove(leftX, topY + borderRadius),
26871
- svgVerticalDeltaLite(delta),
26872
- svgDeltaArc(borderRadius, borderRadius, borderRadius),
26873
- svgHorizontalDeltaLine(delta),
26874
- svgDeltaArc(borderRadius, borderRadius, -borderRadius),
26875
- svgVerticalDeltaLite(-delta),
26876
- svgDeltaArc(borderRadius, -borderRadius, -borderRadius),
26877
- svgHorizontalDeltaLine(-delta),
26878
- svgDeltaArc(borderRadius, -borderRadius, borderRadius),
26901
+ svgMove(leftX, topY + rTL),
26902
+ svgVerticalDeltaLite(size - rTL - rBL),
26903
+ svgDeltaArc(rBL, rBL, rBL),
26904
+ svgHorizontalDeltaLine(size - rBL - rBR),
26905
+ svgDeltaArc(rBR, rBR, -rBR),
26906
+ svgVerticalDeltaLite(-(size - rBR - rTR)),
26907
+ svgDeltaArc(rTR, -rTR, -rTR),
26908
+ svgHorizontalDeltaLine(-(size - rTR - rTL)),
26909
+ svgDeltaArc(rTL, -rTL, rTL),
26879
26910
  svgReturn(),
26880
26911
  ];
26881
26912
  rectangles.push(...rectangle.flat());
@@ -26884,6 +26915,62 @@
26884
26915
  }
26885
26916
  return rectangles.join(" ");
26886
26917
  }
26918
+ const FINDER_SIDES = [[0, 0], [1, 0], [0, 1]];
26919
+ const FINDER_END = 7;
26920
+ function getCornerRadii(shape, sideLength, borderRadius) {
26921
+ const maxR = sideLength / 2;
26922
+ switch (shape) {
26923
+ case 'square': return [0, 0, 0, 0];
26924
+ case 'rounded': return [borderRadius, borderRadius, borderRadius, borderRadius];
26925
+ case 'circle': return [maxR, maxR, maxR, maxR];
26926
+ case 'drop': return [maxR, 0, maxR, maxR];
26927
+ }
26928
+ }
26929
+ function drawFinderRect(xCorner, yCorner, sideLength, xSign, ySign, sweep, cornerRadii) {
26930
+ const [r0, r1, r2, r3] = cornerRadii;
26931
+ return [
26932
+ svgMove(xCorner, yCorner + r3 * ySign),
26933
+ svgVerticalDeltaLite(ySign * (sideLength - r3 - r0)),
26934
+ svgDeltaArc(r0, r0 * xSign, r0 * ySign, sweep),
26935
+ svgHorizontalDeltaLine(xSign * (sideLength - r0 - r1)),
26936
+ svgDeltaArc(r1, r1 * xSign, -r1 * ySign, sweep),
26937
+ svgVerticalDeltaLite(-ySign * (sideLength - r1 - r2)),
26938
+ svgDeltaArc(r2, -r2 * xSign, -r2 * ySign, sweep),
26939
+ svgHorizontalDeltaLine(-xSign * (sideLength - r2 - r3)),
26940
+ svgDeltaArc(r3, -r3 * xSign, r3 * ySign, sweep),
26941
+ svgReturn(),
26942
+ ].flat();
26943
+ }
26944
+ function getFinderOuterSVGPath(matrix, size, margin, borderRadius, shape) {
26945
+ const matrixSize = matrix.length * size + margin * 2;
26946
+ const rectangles = [];
26947
+ for (const side of FINDER_SIDES) {
26948
+ const [xSign, ySign] = side.map(s => s === 0 ? 1 : -1);
26949
+ const sweep = side[1] | side[0];
26950
+ for (const offset of [0, 1]) {
26951
+ const sideLength = size * (FINDER_END - 2 * offset);
26952
+ const xCorner = matrixSize * side[0] + xSign * (margin + size * offset);
26953
+ const yCorner = matrixSize * side[1] + ySign * (margin + size * offset);
26954
+ const radii = getCornerRadii(shape, sideLength, borderRadius);
26955
+ rectangles.push(...drawFinderRect(xCorner, yCorner, sideLength, xSign, ySign, sweep, radii));
26956
+ }
26957
+ }
26958
+ return rectangles.join(" ");
26959
+ }
26960
+ function getFinderInnerSVGPath(matrix, size, margin, borderRadius, shape) {
26961
+ const matrixSize = matrix.length * size + margin * 2;
26962
+ const rectangles = [];
26963
+ for (const side of FINDER_SIDES) {
26964
+ const [xSign, ySign] = side.map(s => s === 0 ? 1 : -1);
26965
+ const sweep = side[1] | side[0];
26966
+ const sideLength = size * (FINDER_END - 2 * 2);
26967
+ const xCorner = matrixSize * side[0] + xSign * (margin + size * 2);
26968
+ const yCorner = matrixSize * side[1] + ySign * (margin + size * 2);
26969
+ const radii = getCornerRadii(shape, sideLength, borderRadius);
26970
+ rectangles.push(...drawFinderRect(xCorner, yCorner, sideLength, xSign, ySign, sweep, radii));
26971
+ }
26972
+ return rectangles.join(" ");
26973
+ }
26887
26974
  const commonOptions = {
26888
26975
  type: "png",
26889
26976
  parse_url: false,
@@ -26992,7 +27079,7 @@
26992
27079
  page.getContentStream = page.prevGetContentStream;
26993
27080
  page.contentStream.push = page.contentStream.prevPush;
26994
27081
  }
26995
- async function PDF({ matrix, margin, logo, logoWidth, logoHeight, color, bgColor, borderRadius, }) {
27082
+ async function PDF({ matrix, margin, logo, logoWidth, logoHeight, color, bgColor, borderRadius, cornerMode, finderOuterShape, finderInnerShape, finderColor, }) {
26996
27083
  const size = 9;
26997
27084
  const marginPx = margin * size;
26998
27085
  const matrixSizePx = matrix.length * size;
@@ -27004,22 +27091,30 @@
27004
27091
  color: rgb(...colorToRGB(bgColor)),
27005
27092
  });
27006
27093
  page.moveTo(0, page.getHeight());
27007
- const path = getDotsSVGPath(matrix, size, marginPx, borderRadius);
27008
- page.drawSvgPath(path, {
27009
- color: rgb(...colorToRGB(color)),
27010
- opacity: getOpacity(color),
27011
- borderColor: rgb(...colorToRGB(color)),
27012
- borderOpacity: getOpacity(color),
27013
- });
27014
- const findersPath = getFindersSVGPath(matrix, size, marginPx, borderRadius);
27015
- patchContentStream(page);
27016
- page.drawSvgPath(findersPath, {
27017
- color: rgb(...colorToRGB(color)),
27018
- opacity: getOpacity(color),
27019
- borderColor: rgb(...colorToRGB(color)),
27020
- borderOpacity: getOpacity(color),
27021
- });
27022
- revertContentStream(page);
27094
+ const fgRGB = rgb(...colorToRGB(color));
27095
+ const fgOpacity = getOpacity(color);
27096
+ const fgStyle = { color: fgRGB, opacity: fgOpacity, borderColor: fgRGB, borderOpacity: fgOpacity };
27097
+ const path = getDotsSVGPath(matrix, size, marginPx, borderRadius, cornerMode);
27098
+ page.drawSvgPath(path, fgStyle);
27099
+ const hasFinderOptions = finderOuterShape || finderInnerShape || finderColor;
27100
+ if (hasFinderOptions) {
27101
+ const fc = finderColor ?? color;
27102
+ const fcRGB = rgb(...colorToRGB(fc));
27103
+ const fcOpacity = getOpacity(fc);
27104
+ const fcStyle = { color: fcRGB, opacity: fcOpacity, borderColor: fcRGB, borderOpacity: fcOpacity };
27105
+ const outerPath = getFinderOuterSVGPath(matrix, size, marginPx, borderRadius, finderOuterShape ?? 'rounded');
27106
+ patchContentStream(page);
27107
+ page.drawSvgPath(outerPath, fcStyle);
27108
+ revertContentStream(page);
27109
+ const innerPath = getFinderInnerSVGPath(matrix, size, marginPx, borderRadius, finderInnerShape ?? 'rounded');
27110
+ page.drawSvgPath(innerPath, fcStyle);
27111
+ }
27112
+ else {
27113
+ const findersPath = getFindersSVGPath(matrix, size, marginPx, borderRadius);
27114
+ patchContentStream(page);
27115
+ page.drawSvgPath(findersPath, fgStyle);
27116
+ revertContentStream(page);
27117
+ }
27023
27118
  if (logo) {
27024
27119
  let logoData;
27025
27120
  const header = new Uint8Array(logo.slice(0, 4));