@sythos/js_barcode_universal 1.5.13 → 1.5.15

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 (137) hide show
  1. package/LICENSE +22 -4
  2. package/NOTICE.md +10 -1
  3. package/README.md +416 -22
  4. package/bundle/sythos-barcode.esm.js +22176 -11991
  5. package/bundle/sythos-barcode.js +22059 -11991
  6. package/licenses/README.md +12 -1
  7. package/licenses/codablockf.license +51 -0
  8. package/licenses/code16k.license +52 -0
  9. package/licenses/code25.license +58 -0
  10. package/licenses/code32.license +51 -0
  11. package/licenses/dotcode.license +66 -0
  12. package/licenses/gs1-composite.license +106 -0
  13. package/licenses/gs1-databar.license +21 -14
  14. package/licenses/hanxin.license +95 -0
  15. package/licenses/maxicode.license +62 -0
  16. package/licenses/postal.license +61 -0
  17. package/licenses/pzn.license +53 -0
  18. package/licenses/telepen.license +73 -0
  19. package/llms.txt +62 -6
  20. package/package.json +47 -3
  21. package/src/index.d.ts +111 -6
  22. package/src/index.js +362 -13
  23. package/src/js/codablockf/decoder.js +198 -0
  24. package/src/js/codablockf/encoder.js +97 -0
  25. package/src/js/codablockf/index.js +3 -0
  26. package/src/js/code16k/decoder.js +303 -0
  27. package/src/js/code16k/detector.js +187 -0
  28. package/src/js/code16k/encoder.js +153 -0
  29. package/src/js/code16k/index.js +14 -0
  30. package/src/js/code16k/tables.js +152 -0
  31. package/src/js/composite/index.js +570 -0
  32. package/src/js/core/detection-contract.js +185 -0
  33. package/src/js/core/symbol-layout.js +155 -0
  34. package/src/js/databar/expanded.js +968 -0
  35. package/src/js/databar/index.js +4 -0
  36. package/src/js/databar/layout.js +192 -0
  37. package/src/js/databar/limited.js +533 -0
  38. package/src/js/databar/stacked-omnidirectional.js +548 -0
  39. package/src/js/databar/stacked.js +528 -0
  40. package/src/js/dotcode/decoder.js +548 -0
  41. package/src/js/dotcode/detector.js +251 -0
  42. package/src/js/dotcode/encoder.js +453 -0
  43. package/src/js/dotcode/index.js +34 -0
  44. package/src/js/dotcode/tables.js +168 -0
  45. package/src/js/hanxin/decoder.js +299 -0
  46. package/src/js/hanxin/detector.js +122 -0
  47. package/src/js/hanxin/encoder.js +259 -0
  48. package/src/js/hanxin/index.js +16 -0
  49. package/src/js/hanxin/tables.js +316 -0
  50. package/src/js/image/height-coded.js +164 -0
  51. package/src/js/maxicode/decoder.js +275 -0
  52. package/src/js/maxicode/detector.js +118 -0
  53. package/src/js/maxicode/encoder.js +438 -0
  54. package/src/js/maxicode/index.js +34 -0
  55. package/src/js/maxicode/tables.js +132 -0
  56. package/src/js/oned/code25.js +148 -0
  57. package/src/js/oned/index.js +21 -3
  58. package/src/js/oned/postal.js +889 -0
  59. package/src/js/oned/reader.js +272 -7
  60. package/src/js/oned/telepen.js +361 -0
  61. package/src/js/oned/writers.js +186 -12
  62. package/src/js/stacked128/common.js +208 -0
  63. package/src/ts/codablockf/decoder.ts +212 -0
  64. package/src/ts/codablockf/encoder.ts +128 -0
  65. package/src/ts/codablockf/index.d.ts +31 -0
  66. package/src/ts/codablockf/index.ts +6 -0
  67. package/src/ts/code16k/decoder.d.ts +25 -0
  68. package/src/ts/code16k/decoder.ts +313 -0
  69. package/src/ts/code16k/detector.d.ts +21 -0
  70. package/src/ts/code16k/detector.ts +203 -0
  71. package/src/ts/code16k/encoder.d.ts +26 -0
  72. package/src/ts/code16k/encoder.ts +198 -0
  73. package/src/ts/code16k/index.d.ts +10 -0
  74. package/src/ts/code16k/index.ts +47 -0
  75. package/src/ts/code16k/tables.d.ts +54 -0
  76. package/src/ts/code16k/tables.ts +195 -0
  77. package/src/ts/composite/index.d.ts +74 -0
  78. package/src/ts/composite/index.ts +547 -0
  79. package/src/ts/core/detection-contract.d.ts +119 -0
  80. package/src/ts/core/detection-contract.ts +267 -0
  81. package/src/ts/core/symbol-layout.d.ts +108 -0
  82. package/src/ts/core/symbol-layout.ts +236 -0
  83. package/src/ts/databar/expanded.d.ts +40 -0
  84. package/src/ts/databar/expanded.ts +948 -0
  85. package/src/ts/databar/index.d.ts +48 -0
  86. package/src/ts/databar/index.ts +48 -0
  87. package/src/ts/databar/layout.d.ts +122 -0
  88. package/src/ts/databar/layout.ts +275 -0
  89. package/src/ts/databar/limited.d.ts +85 -0
  90. package/src/ts/databar/limited.ts +553 -0
  91. package/src/ts/databar/stacked-omnidirectional.d.ts +128 -0
  92. package/src/ts/databar/stacked-omnidirectional.ts +559 -0
  93. package/src/ts/databar/stacked.d.ts +96 -0
  94. package/src/ts/databar/stacked.ts +549 -0
  95. package/src/ts/dotcode/decoder.d.ts +58 -0
  96. package/src/ts/dotcode/decoder.ts +467 -0
  97. package/src/ts/dotcode/detector.d.ts +63 -0
  98. package/src/ts/dotcode/detector.ts +263 -0
  99. package/src/ts/dotcode/encoder.d.ts +69 -0
  100. package/src/ts/dotcode/encoder.ts +427 -0
  101. package/src/ts/dotcode/index.d.ts +37 -0
  102. package/src/ts/dotcode/index.ts +72 -0
  103. package/src/ts/dotcode/tables.d.ts +74 -0
  104. package/src/ts/dotcode/tables.ts +174 -0
  105. package/src/ts/hanxin/decoder.d.ts +48 -0
  106. package/src/ts/hanxin/decoder.ts +314 -0
  107. package/src/ts/hanxin/detector.d.ts +45 -0
  108. package/src/ts/hanxin/detector.ts +124 -0
  109. package/src/ts/hanxin/encoder.d.ts +41 -0
  110. package/src/ts/hanxin/encoder.ts +290 -0
  111. package/src/ts/hanxin/index.d.ts +16 -0
  112. package/src/ts/hanxin/index.ts +18 -0
  113. package/src/ts/hanxin/tables.d.ts +80 -0
  114. package/src/ts/hanxin/tables.ts +348 -0
  115. package/src/ts/image/height-coded.d.ts +101 -0
  116. package/src/ts/image/height-coded.ts +227 -0
  117. package/src/ts/index.d.ts +46 -2
  118. package/src/ts/index.ts +380 -13
  119. package/src/ts/maxicode/decoder.ts +265 -0
  120. package/src/ts/maxicode/detector.ts +109 -0
  121. package/src/ts/maxicode/encoder.ts +414 -0
  122. package/src/ts/maxicode/index.d.ts +96 -0
  123. package/src/ts/maxicode/index.ts +44 -0
  124. package/src/ts/maxicode/tables.ts +136 -0
  125. package/src/ts/oned/code25.d.ts +42 -0
  126. package/src/ts/oned/code25.ts +170 -0
  127. package/src/ts/oned/index.d.ts +7 -2
  128. package/src/ts/oned/index.ts +45 -3
  129. package/src/ts/oned/postal.d.ts +44 -0
  130. package/src/ts/oned/postal.ts +819 -0
  131. package/src/ts/oned/reader.d.ts +35 -0
  132. package/src/ts/oned/reader.ts +261 -7
  133. package/src/ts/oned/telepen.d.ts +65 -0
  134. package/src/ts/oned/telepen.ts +368 -0
  135. package/src/ts/oned/writers.d.ts +32 -0
  136. package/src/ts/oned/writers.ts +184 -13
  137. package/src/ts/stacked128/common.ts +225 -0
@@ -0,0 +1,185 @@
1
+ /*!
2
+ * Sythos Barcode Suite
3
+ *
4
+ * MIT License
5
+ *
6
+ * Copyright (c) 2026 Sythos
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all
16
+ * copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ * SOFTWARE.
25
+ *
26
+ * SPDX-FileCopyrightText: 2026 Sythos (https://www.sythos.net)
27
+ * SPDX-License-Identifier: MIT
28
+ *
29
+ * Original work. No code from any other barcode implementation.
30
+ */
31
+ function hasOwn(value, property) {
32
+ return Object.prototype.hasOwnProperty.call(value, property);
33
+ }
34
+ function isRecord(value) {
35
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
36
+ }
37
+ function isFiniteNumber(value) {
38
+ return typeof value === 'number' && Number.isFinite(value);
39
+ }
40
+ function cross(a, b, c) {
41
+ return (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);
42
+ }
43
+ /**
44
+ * Normalize a detector rotation to one of the supported 45-degree turns.
45
+ *
46
+ * This function is intentionally strict: arbitrary angles are not silently
47
+ * snapped to a nearby orientation. The accepted domain is the integer range
48
+ * `0..359`, and only exact multiples of 45 degrees are canonical.
49
+ *
50
+ * @throws {TypeError} If `rotation` is not a number.
51
+ * @throws {RangeError} If `rotation` is outside the canonical domain.
52
+ */
53
+ export function normalizeRotation(rotation) {
54
+ if (typeof rotation !== 'number') {
55
+ throw new TypeError('Rotation must be a number');
56
+ }
57
+ if (!Number.isFinite(rotation) || !Number.isInteger(rotation)
58
+ || rotation < 0 || rotation >= 360 || rotation % 45 !== 0) {
59
+ throw new RangeError('Rotation must be an integer multiple of 45 degrees in 0..359');
60
+ }
61
+ return rotation;
62
+ }
63
+ /**
64
+ * Return whether four finite points form an ordered, non-degenerate quad.
65
+ *
66
+ * The required order is top-left, top-right, bottom-right, bottom-left. Both
67
+ * clockwise and counter-clockwise winding are accepted; repeated points,
68
+ * zero-length edges, collinear turns, concave quads, and self-intersections
69
+ * are rejected.
70
+ */
71
+ export function isValidCorners(corners) {
72
+ if (!Array.isArray(corners) || corners.length !== 4)
73
+ return false;
74
+ const points = [];
75
+ for (const value of corners) {
76
+ if (!isRecord(value) || !isFiniteNumber(value.x) || !isFiniteNumber(value.y)) {
77
+ return false;
78
+ }
79
+ points.push({ x: value.x, y: value.y });
80
+ }
81
+ for (let first = 0; first < points.length; first++) {
82
+ for (let second = first + 1; second < points.length; second++) {
83
+ if (points[first].x === points[second].x && points[first].y === points[second].y) {
84
+ return false;
85
+ }
86
+ }
87
+ }
88
+ let winding = 0;
89
+ for (let index = 0; index < points.length; index++) {
90
+ const turn = cross(points[index], points[(index + 1) % points.length], points[(index + 2) % points.length]);
91
+ if (!Number.isFinite(turn) || turn === 0)
92
+ return false;
93
+ const sign = Math.sign(turn);
94
+ if (winding === 0)
95
+ winding = sign;
96
+ else if (sign !== winding)
97
+ return false;
98
+ }
99
+ return true;
100
+ }
101
+ function isValidQuality(value) {
102
+ if (!isRecord(value))
103
+ return false;
104
+ if (hasOwn(value, 'quietZone') && typeof value.quietZone !== 'boolean')
105
+ return false;
106
+ if (hasOwn(value, 'checksum')
107
+ && value.checksum !== null && typeof value.checksum !== 'boolean')
108
+ return false;
109
+ if (hasOwn(value, 'rows') && value.rows !== null
110
+ && (!isFiniteNumber(value.rows) || !Number.isInteger(value.rows) || value.rows < 0)) {
111
+ return false;
112
+ }
113
+ if (hasOwn(value, 'consistency') && value.consistency !== null
114
+ && (!isFiniteNumber(value.consistency) || value.consistency < 0 || value.consistency > 1)) {
115
+ return false;
116
+ }
117
+ return true;
118
+ }
119
+ function isValidConfidence(value) {
120
+ return value === undefined
121
+ || (isFiniteNumber(value) && value >= 0 && value <= 1);
122
+ }
123
+ function isValidScore(value) {
124
+ return value === undefined || isFiniteNumber(value);
125
+ }
126
+ /**
127
+ * Create a validated detector candidate.
128
+ *
129
+ * All optional decoded-result and ranking metadata must be supplied in the
130
+ * options object: `createDetectionCandidate(geometry, { result, quality, score })`.
131
+ * Keeping the decoded result under the explicit `result` key avoids confusing
132
+ * a result object with candidate metadata. The returned value owns a fresh
133
+ * corner array and canonical rotation, and the input objects are never
134
+ * mutated.
135
+ *
136
+ * @throws {TypeError} If the geometry, matrix, or options have an invalid type.
137
+ * @throws {RangeError} If a numeric geometry or metadata value is invalid.
138
+ */
139
+ export function createDetectionCandidate(geometry, options) {
140
+ if (!isRecord(geometry)) {
141
+ throw new TypeError('Detection geometry must be an object');
142
+ }
143
+ const geometryValue = geometry;
144
+ const corners = geometryValue.corners;
145
+ if (!isValidCorners(corners)) {
146
+ throw new RangeError('Detection geometry must contain four non-degenerate corners');
147
+ }
148
+ const moduleSize = geometryValue.moduleSize;
149
+ if (!isFiniteNumber(moduleSize) || moduleSize <= 0) {
150
+ throw new RangeError('Detection geometry moduleSize must be a positive finite number');
151
+ }
152
+ const rotation = normalizeRotation(geometryValue.rotation);
153
+ if (!hasOwn(geometryValue, 'matrix') || geometryValue.matrix === null
154
+ || geometryValue.matrix === undefined) {
155
+ throw new TypeError('Detection geometry must contain a matrix');
156
+ }
157
+ if (!isValidConfidence(geometryValue.confidence)) {
158
+ throw new RangeError('Detection geometry confidence must be a finite number in 0..1');
159
+ }
160
+ const candidateOptions = options === undefined ? {} : options;
161
+ if (!isRecord(candidateOptions)) {
162
+ throw new TypeError('Detection candidate options must be an object');
163
+ }
164
+ const validatedOptions = candidateOptions;
165
+ const quality = validatedOptions.quality;
166
+ if (quality !== undefined && !isValidQuality(quality)) {
167
+ throw new TypeError('Detection candidate quality must be an object');
168
+ }
169
+ if (!isValidScore(validatedOptions.score)) {
170
+ throw new RangeError('Detection candidate score must be a finite number');
171
+ }
172
+ const candidate = {
173
+ ...geometry,
174
+ corners: corners.map((point) => ({ x: point.x, y: point.y })),
175
+ moduleSize,
176
+ rotation,
177
+ };
178
+ if (hasOwn(validatedOptions, 'result') && validatedOptions.result !== undefined)
179
+ candidate.result = validatedOptions.result;
180
+ if (hasOwn(validatedOptions, 'quality') && quality !== undefined)
181
+ candidate.quality = quality;
182
+ if (hasOwn(validatedOptions, 'score') && validatedOptions.score !== undefined)
183
+ candidate.score = validatedOptions.score;
184
+ return candidate;
185
+ }
@@ -0,0 +1,155 @@
1
+ /*!
2
+ * Sythos Barcode Suite
3
+ *
4
+ * MIT License
5
+ *
6
+ * Copyright (c) 2026 Sythos
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all
16
+ * copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ * SOFTWARE.
25
+ *
26
+ * SPDX-License-Identifier: MIT
27
+ *
28
+ * Original work. No code from any other barcode implementation.
29
+ */
30
+ /*
31
+ * These limits are intentionally conservative. They keep this foundation safe
32
+ * for future matrix allocators while allowing the largest practical barcode
33
+ * geometries. The implementation never allocates based on a descriptor.
34
+ */
35
+ const MAX_LAYOUT_DIMENSION = 32768;
36
+ const MAX_LAYOUT_MODULES = 16777216;
37
+ const hasOwn = (value, property) => Object.prototype.hasOwnProperty.call(value, property);
38
+ function isBoundedPositiveInteger(value, maximum) {
39
+ return typeof value === 'number'
40
+ && Number.isFinite(value)
41
+ && Number.isInteger(value)
42
+ && value > 0
43
+ && value <= maximum;
44
+ }
45
+ function isRecord(value) {
46
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
47
+ }
48
+ /**
49
+ * Check that the descriptor's full panel footprint stays within the allocation
50
+ * budget. The quiet zone is included in the footprint because a later renderer
51
+ * may materialize it alongside the active modules.
52
+ */
53
+ function isWithinModuleBudget(width, height, quietZone, rows, columns) {
54
+ const footprintWidth = width + quietZone * 2;
55
+ const footprintHeight = height + quietZone * 2;
56
+ if (footprintWidth > MAX_LAYOUT_DIMENSION || footprintHeight > MAX_LAYOUT_DIMENSION) {
57
+ return false;
58
+ }
59
+ let total = footprintWidth;
60
+ if (total > MAX_LAYOUT_MODULES / footprintHeight)
61
+ return false;
62
+ total *= footprintHeight;
63
+ if (total > MAX_LAYOUT_MODULES / rows)
64
+ return false;
65
+ total *= rows;
66
+ if (total > MAX_LAYOUT_MODULES / columns)
67
+ return false;
68
+ return total * columns <= MAX_LAYOUT_MODULES;
69
+ }
70
+ /**
71
+ * Return whether an unknown value is a valid symbol layout descriptor.
72
+ *
73
+ * Validation is side-effect free and performs no matrix allocation. A valid
74
+ * descriptor may be mutable when supplied by a caller; use
75
+ * {@link createSymbolLayout} when an immutable value is required.
76
+ */
77
+ export function validateSymbolLayout(value) {
78
+ if (!isRecord(value))
79
+ return false;
80
+ if (!hasOwn(value, 'moduleShape') || (value.moduleShape !== 'square' && value.moduleShape !== 'dot')) {
81
+ return false;
82
+ }
83
+ if (!hasOwn(value, 'lattice') || (value.lattice !== 'square' && value.lattice !== 'hex')) {
84
+ return false;
85
+ }
86
+ if (!hasOwn(value, 'width') || !isBoundedPositiveInteger(value.width, MAX_LAYOUT_DIMENSION)) {
87
+ return false;
88
+ }
89
+ if (!hasOwn(value, 'height') || !isBoundedPositiveInteger(value.height, MAX_LAYOUT_DIMENSION)) {
90
+ return false;
91
+ }
92
+ if (!hasOwn(value, 'quietZone') || !isBoundedPositiveInteger(value.quietZone, MAX_LAYOUT_DIMENSION)) {
93
+ return false;
94
+ }
95
+ const rows = value.rows;
96
+ if (rows !== undefined
97
+ && (!hasOwn(value, 'rows') || !isBoundedPositiveInteger(rows, MAX_LAYOUT_DIMENSION))) {
98
+ return false;
99
+ }
100
+ const columns = value.columns;
101
+ if (columns !== undefined
102
+ && (!hasOwn(value, 'columns') || !isBoundedPositiveInteger(columns, MAX_LAYOUT_DIMENSION))) {
103
+ return false;
104
+ }
105
+ const rowCount = rows === undefined ? 1 : rows;
106
+ const columnCount = columns === undefined ? 1 : columns;
107
+ return isWithinModuleBudget(value.width, value.height, value.quietZone, rowCount, columnCount);
108
+ }
109
+ /**
110
+ * Create a validated, shallowly immutable symbol layout descriptor.
111
+ *
112
+ * Only the documented fields are copied. Unknown input properties are ignored,
113
+ * so a future caller can pass a richer format-specific object without leaking
114
+ * mutable implementation state into the shared descriptor.
115
+ *
116
+ * @throws {TypeError} If `options` is not an object.
117
+ * @throws {RangeError} If any field is invalid or exceeds the safe budget.
118
+ */
119
+ export function createSymbolLayout(options) {
120
+ if (!isRecord(options)) {
121
+ throw new TypeError('Symbol layout options must be an object');
122
+ }
123
+ const descriptor = {
124
+ moduleShape: options.moduleShape,
125
+ lattice: options.lattice,
126
+ width: options.width,
127
+ height: options.height,
128
+ quietZone: options.quietZone,
129
+ };
130
+ if (options.rows !== undefined)
131
+ descriptor.rows = options.rows;
132
+ if (options.columns !== undefined)
133
+ descriptor.columns = options.columns;
134
+ if (!validateSymbolLayout(descriptor)) {
135
+ throw new RangeError('Invalid symbol layout descriptor');
136
+ }
137
+ return Object.freeze(descriptor);
138
+ }
139
+ /**
140
+ * Count logical modules in a complete layout without allocating a matrix.
141
+ *
142
+ * Optional rows and columns multiply the panel dimensions. Quiet-zone modules
143
+ * are intentionally excluded: this helper reports symbol modules, while the
144
+ * validation budget also protects the future rendered footprint.
145
+ *
146
+ * @throws {TypeError} If `layout` is not a valid descriptor.
147
+ */
148
+ export function layoutModuleCount(layout) {
149
+ if (!validateSymbolLayout(layout)) {
150
+ throw new TypeError('Cannot count modules for an invalid symbol layout');
151
+ }
152
+ const rows = layout.rows === undefined ? 1 : layout.rows;
153
+ const columns = layout.columns === undefined ? 1 : layout.columns;
154
+ return layout.width * layout.height * rows * columns;
155
+ }