001/*
002 * Copyright 2007 ZXing authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.itextpdf.text.pdf.qrcode;
018
019/**
020 * See ISO 18004:2006 Annex D
021 *
022 * @author Sean Owen
023 * @since 5.0.2
024 */
025public final class Version {
026
027  /**
028   * See ISO 18004:2006 Annex D.
029   * Element i represents the raw version bits that specify version i + 7
030   */
031  private static final int[] VERSION_DECODE_INFO = {
032      0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
033      0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
034      0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,
035      0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
036      0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,
037      0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
038      0x2542E, 0x26A64, 0x27541, 0x28C69
039  };
040
041  private static final Version[] VERSIONS = buildVersions();
042
043  private final int versionNumber;
044  private final int[] alignmentPatternCenters;
045  private final ECBlocks[] ecBlocks;
046  private final int totalCodewords;
047
048  private Version(int versionNumber,
049                  int[] alignmentPatternCenters,
050                  ECBlocks ecBlocks1,
051                  ECBlocks ecBlocks2,
052                  ECBlocks ecBlocks3,
053                  ECBlocks ecBlocks4) {
054    this.versionNumber = versionNumber;
055    this.alignmentPatternCenters = alignmentPatternCenters;
056    this.ecBlocks = new ECBlocks[]{ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4};
057    int total = 0;
058    int ecCodewords = ecBlocks1.getECCodewordsPerBlock();
059    ECB[] ecbArray = ecBlocks1.getECBlocks();
060    for (int i = 0; i < ecbArray.length; i++) {
061      ECB ecBlock = ecbArray[i];
062      total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
063    }
064    this.totalCodewords = total;
065  }
066
067  public int getVersionNumber() {
068    return versionNumber;
069  }
070
071  public int[] getAlignmentPatternCenters() {
072    return alignmentPatternCenters;
073  }
074
075  public int getTotalCodewords() {
076    return totalCodewords;
077  }
078
079  public int getDimensionForVersion() {
080    return 17 + 4 * versionNumber;
081  }
082
083  public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {
084    return ecBlocks[ecLevel.ordinal()];
085  }
086
087  /**
088   * <p>Deduces version information purely from QR Code dimensions.</p>
089   *
090   * @param dimension dimension in modules
091   * @return {@link Version} for a QR Code of that dimension
092   * @throws FormatException if dimension is not 1 mod 4
093   */
094  public static Version getProvisionalVersionForDimension(int dimension) {
095    if (dimension % 4 != 1) {
096      throw new IllegalArgumentException();
097    }
098    try {
099      return getVersionForNumber((dimension - 17) >> 2);
100    } catch (IllegalArgumentException iae) {
101      throw iae;
102    }
103  }
104
105  public static Version getVersionForNumber(int versionNumber) {
106    if (versionNumber < 1 || versionNumber > 40) {
107      throw new IllegalArgumentException();
108    }
109    return VERSIONS[versionNumber - 1];
110  }
111
112  static Version decodeVersionInformation(int versionBits) {
113    int bestDifference = Integer.MAX_VALUE;
114    int bestVersion = 0;
115    for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {
116      int targetVersion = VERSION_DECODE_INFO[i];
117      // Do the version info bits match exactly? done.
118      if (targetVersion == versionBits) {
119        return getVersionForNumber(i + 7);
120      }
121      // Otherwise see if this is the closest to a real version info bit string
122      // we have seen so far
123      int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);
124      if (bitsDifference < bestDifference) {
125        bestVersion = i + 7;
126        bestDifference = bitsDifference;
127      }
128    }
129    // We can tolerate up to 3 bits of error since no two version info codewords will
130    // differ in less than 4 bits.
131    if (bestDifference <= 3) {
132      return getVersionForNumber(bestVersion);
133    }
134    // If we didn't find a close enough match, fail
135    return null;
136  }
137
138  /**
139   * See ISO 18004:2006 Annex E
140   */
141  BitMatrix buildFunctionPattern() {
142    int dimension = getDimensionForVersion();
143    BitMatrix bitMatrix = new BitMatrix(dimension);
144
145    // Top left finder pattern + separator + format
146    bitMatrix.setRegion(0, 0, 9, 9);
147    // Top right finder pattern + separator + format
148    bitMatrix.setRegion(dimension - 8, 0, 8, 9);
149    // Bottom left finder pattern + separator + format
150    bitMatrix.setRegion(0, dimension - 8, 9, 8);
151
152    // Alignment patterns
153    int max = alignmentPatternCenters.length;
154    for (int x = 0; x < max; x++) {
155      int i = alignmentPatternCenters[x] - 2;
156      for (int y = 0; y < max; y++) {
157        if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
158          // No alignment patterns near the three finder paterns
159          continue;
160        }
161        bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);
162      }
163    }
164
165    // Vertical timing pattern
166    bitMatrix.setRegion(6, 9, 1, dimension - 17);
167    // Horizontal timing pattern
168    bitMatrix.setRegion(9, 6, dimension - 17, 1);
169
170    if (versionNumber > 6) {
171      // Version info, top right
172      bitMatrix.setRegion(dimension - 11, 0, 3, 6);
173      // Version info, bottom left
174      bitMatrix.setRegion(0, dimension - 11, 6, 3);
175    }
176
177    return bitMatrix;
178  }
179
180  /**
181   * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
182   * use blocks of differing sizes within one version, so, this encapsulates the parameters for
183   * each set of blocks. It also holds the number of error-correction codewords per block since it
184   * will be the same across all blocks within one version.</p>
185   */
186  public static final class ECBlocks {
187    private final int ecCodewordsPerBlock;
188    private final ECB[] ecBlocks;
189
190    ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks) {
191      this.ecCodewordsPerBlock = ecCodewordsPerBlock;
192      this.ecBlocks = new ECB[]{ecBlocks};
193    }
194
195    ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks1, ECB ecBlocks2) {
196      this.ecCodewordsPerBlock = ecCodewordsPerBlock;
197      this.ecBlocks = new ECB[]{ecBlocks1, ecBlocks2};
198    }
199
200    public int getECCodewordsPerBlock() {
201      return ecCodewordsPerBlock;
202    }
203
204    public int getNumBlocks() {
205      int total = 0;
206      for (int i = 0; i < ecBlocks.length; i++) {
207        total += ecBlocks[i].getCount();
208      }
209      return total;
210    }
211
212    public int getTotalECCodewords() {
213      return ecCodewordsPerBlock * getNumBlocks();
214    }
215
216    public ECB[] getECBlocks() {
217      return ecBlocks;
218    }
219  }
220
221  /**
222   * <p>Encapsualtes the parameters for one error-correction block in one symbol version.
223   * This includes the number of data codewords, and the number of times a block with these
224   * parameters is used consecutively in the QR code version's format.</p>
225   */
226  public static final class ECB {
227    private final int count;
228    private final int dataCodewords;
229
230    ECB(int count, int dataCodewords) {
231      this.count = count;
232      this.dataCodewords = dataCodewords;
233    }
234
235    public int getCount() {
236      return count;
237    }
238
239    public int getDataCodewords() {
240      return dataCodewords;
241    }
242  }
243
244  public String toString() {
245    return String.valueOf(versionNumber);
246  }
247
248  /**
249   * See ISO 18004:2006 6.5.1 Table 9
250   */
251  private static Version[] buildVersions() {
252    return new Version[]{
253        new Version(1, new int[]{},
254            new ECBlocks(7, new ECB(1, 19)),
255            new ECBlocks(10, new ECB(1, 16)),
256            new ECBlocks(13, new ECB(1, 13)),
257            new ECBlocks(17, new ECB(1, 9))),
258        new Version(2, new int[]{6, 18},
259            new ECBlocks(10, new ECB(1, 34)),
260            new ECBlocks(16, new ECB(1, 28)),
261            new ECBlocks(22, new ECB(1, 22)),
262            new ECBlocks(28, new ECB(1, 16))),
263        new Version(3, new int[]{6, 22},
264            new ECBlocks(15, new ECB(1, 55)),
265            new ECBlocks(26, new ECB(1, 44)),
266            new ECBlocks(18, new ECB(2, 17)),
267            new ECBlocks(22, new ECB(2, 13))),
268        new Version(4, new int[]{6, 26},
269            new ECBlocks(20, new ECB(1, 80)),
270            new ECBlocks(18, new ECB(2, 32)),
271            new ECBlocks(26, new ECB(2, 24)),
272            new ECBlocks(16, new ECB(4, 9))),
273        new Version(5, new int[]{6, 30},
274            new ECBlocks(26, new ECB(1, 108)),
275            new ECBlocks(24, new ECB(2, 43)),
276            new ECBlocks(18, new ECB(2, 15),
277                new ECB(2, 16)),
278            new ECBlocks(22, new ECB(2, 11),
279                new ECB(2, 12))),
280        new Version(6, new int[]{6, 34},
281            new ECBlocks(18, new ECB(2, 68)),
282            new ECBlocks(16, new ECB(4, 27)),
283            new ECBlocks(24, new ECB(4, 19)),
284            new ECBlocks(28, new ECB(4, 15))),
285        new Version(7, new int[]{6, 22, 38},
286            new ECBlocks(20, new ECB(2, 78)),
287            new ECBlocks(18, new ECB(4, 31)),
288            new ECBlocks(18, new ECB(2, 14),
289                new ECB(4, 15)),
290            new ECBlocks(26, new ECB(4, 13),
291                new ECB(1, 14))),
292        new Version(8, new int[]{6, 24, 42},
293            new ECBlocks(24, new ECB(2, 97)),
294            new ECBlocks(22, new ECB(2, 38),
295                new ECB(2, 39)),
296            new ECBlocks(22, new ECB(4, 18),
297                new ECB(2, 19)),
298            new ECBlocks(26, new ECB(4, 14),
299                new ECB(2, 15))),
300        new Version(9, new int[]{6, 26, 46},
301            new ECBlocks(30, new ECB(2, 116)),
302            new ECBlocks(22, new ECB(3, 36),
303                new ECB(2, 37)),
304            new ECBlocks(20, new ECB(4, 16),
305                new ECB(4, 17)),
306            new ECBlocks(24, new ECB(4, 12),
307                new ECB(4, 13))),
308        new Version(10, new int[]{6, 28, 50},
309            new ECBlocks(18, new ECB(2, 68),
310                new ECB(2, 69)),
311            new ECBlocks(26, new ECB(4, 43),
312                new ECB(1, 44)),
313            new ECBlocks(24, new ECB(6, 19),
314                new ECB(2, 20)),
315            new ECBlocks(28, new ECB(6, 15),
316                new ECB(2, 16))),
317        new Version(11, new int[]{6, 30, 54},
318            new ECBlocks(20, new ECB(4, 81)),
319            new ECBlocks(30, new ECB(1, 50),
320                new ECB(4, 51)),
321            new ECBlocks(28, new ECB(4, 22),
322                new ECB(4, 23)),
323            new ECBlocks(24, new ECB(3, 12),
324                new ECB(8, 13))),
325        new Version(12, new int[]{6, 32, 58},
326            new ECBlocks(24, new ECB(2, 92),
327                new ECB(2, 93)),
328            new ECBlocks(22, new ECB(6, 36),
329                new ECB(2, 37)),
330            new ECBlocks(26, new ECB(4, 20),
331                new ECB(6, 21)),
332            new ECBlocks(28, new ECB(7, 14),
333                new ECB(4, 15))),
334        new Version(13, new int[]{6, 34, 62},
335            new ECBlocks(26, new ECB(4, 107)),
336            new ECBlocks(22, new ECB(8, 37),
337                new ECB(1, 38)),
338            new ECBlocks(24, new ECB(8, 20),
339                new ECB(4, 21)),
340            new ECBlocks(22, new ECB(12, 11),
341                new ECB(4, 12))),
342        new Version(14, new int[]{6, 26, 46, 66},
343            new ECBlocks(30, new ECB(3, 115),
344                new ECB(1, 116)),
345            new ECBlocks(24, new ECB(4, 40),
346                new ECB(5, 41)),
347            new ECBlocks(20, new ECB(11, 16),
348                new ECB(5, 17)),
349            new ECBlocks(24, new ECB(11, 12),
350                new ECB(5, 13))),
351        new Version(15, new int[]{6, 26, 48, 70},
352            new ECBlocks(22, new ECB(5, 87),
353                new ECB(1, 88)),
354            new ECBlocks(24, new ECB(5, 41),
355                new ECB(5, 42)),
356            new ECBlocks(30, new ECB(5, 24),
357                new ECB(7, 25)),
358            new ECBlocks(24, new ECB(11, 12),
359                new ECB(7, 13))),
360        new Version(16, new int[]{6, 26, 50, 74},
361            new ECBlocks(24, new ECB(5, 98),
362                new ECB(1, 99)),
363            new ECBlocks(28, new ECB(7, 45),
364                new ECB(3, 46)),
365            new ECBlocks(24, new ECB(15, 19),
366                new ECB(2, 20)),
367            new ECBlocks(30, new ECB(3, 15),
368                new ECB(13, 16))),
369        new Version(17, new int[]{6, 30, 54, 78},
370            new ECBlocks(28, new ECB(1, 107),
371                new ECB(5, 108)),
372            new ECBlocks(28, new ECB(10, 46),
373                new ECB(1, 47)),
374            new ECBlocks(28, new ECB(1, 22),
375                new ECB(15, 23)),
376            new ECBlocks(28, new ECB(2, 14),
377                new ECB(17, 15))),
378        new Version(18, new int[]{6, 30, 56, 82},
379            new ECBlocks(30, new ECB(5, 120),
380                new ECB(1, 121)),
381            new ECBlocks(26, new ECB(9, 43),
382                new ECB(4, 44)),
383            new ECBlocks(28, new ECB(17, 22),
384                new ECB(1, 23)),
385            new ECBlocks(28, new ECB(2, 14),
386                new ECB(19, 15))),
387        new Version(19, new int[]{6, 30, 58, 86},
388            new ECBlocks(28, new ECB(3, 113),
389                new ECB(4, 114)),
390            new ECBlocks(26, new ECB(3, 44),
391                new ECB(11, 45)),
392            new ECBlocks(26, new ECB(17, 21),
393                new ECB(4, 22)),
394            new ECBlocks(26, new ECB(9, 13),
395                new ECB(16, 14))),
396        new Version(20, new int[]{6, 34, 62, 90},
397            new ECBlocks(28, new ECB(3, 107),
398                new ECB(5, 108)),
399            new ECBlocks(26, new ECB(3, 41),
400                new ECB(13, 42)),
401            new ECBlocks(30, new ECB(15, 24),
402                new ECB(5, 25)),
403            new ECBlocks(28, new ECB(15, 15),
404                new ECB(10, 16))),
405        new Version(21, new int[]{6, 28, 50, 72, 94},
406            new ECBlocks(28, new ECB(4, 116),
407                new ECB(4, 117)),
408            new ECBlocks(26, new ECB(17, 42)),
409            new ECBlocks(28, new ECB(17, 22),
410                new ECB(6, 23)),
411            new ECBlocks(30, new ECB(19, 16),
412                new ECB(6, 17))),
413        new Version(22, new int[]{6, 26, 50, 74, 98},
414            new ECBlocks(28, new ECB(2, 111),
415                new ECB(7, 112)),
416            new ECBlocks(28, new ECB(17, 46)),
417            new ECBlocks(30, new ECB(7, 24),
418                new ECB(16, 25)),
419            new ECBlocks(24, new ECB(34, 13))),
420        new Version(23, new int[]{6, 30, 54, 74, 102},
421            new ECBlocks(30, new ECB(4, 121),
422                new ECB(5, 122)),
423            new ECBlocks(28, new ECB(4, 47),
424                new ECB(14, 48)),
425            new ECBlocks(30, new ECB(11, 24),
426                new ECB(14, 25)),
427            new ECBlocks(30, new ECB(16, 15),
428                new ECB(14, 16))),
429        new Version(24, new int[]{6, 28, 54, 80, 106},
430            new ECBlocks(30, new ECB(6, 117),
431                new ECB(4, 118)),
432            new ECBlocks(28, new ECB(6, 45),
433                new ECB(14, 46)),
434            new ECBlocks(30, new ECB(11, 24),
435                new ECB(16, 25)),
436            new ECBlocks(30, new ECB(30, 16),
437                new ECB(2, 17))),
438        new Version(25, new int[]{6, 32, 58, 84, 110},
439            new ECBlocks(26, new ECB(8, 106),
440                new ECB(4, 107)),
441            new ECBlocks(28, new ECB(8, 47),
442                new ECB(13, 48)),
443            new ECBlocks(30, new ECB(7, 24),
444                new ECB(22, 25)),
445            new ECBlocks(30, new ECB(22, 15),
446                new ECB(13, 16))),
447        new Version(26, new int[]{6, 30, 58, 86, 114},
448            new ECBlocks(28, new ECB(10, 114),
449                new ECB(2, 115)),
450            new ECBlocks(28, new ECB(19, 46),
451                new ECB(4, 47)),
452            new ECBlocks(28, new ECB(28, 22),
453                new ECB(6, 23)),
454            new ECBlocks(30, new ECB(33, 16),
455                new ECB(4, 17))),
456        new Version(27, new int[]{6, 34, 62, 90, 118},
457            new ECBlocks(30, new ECB(8, 122),
458                new ECB(4, 123)),
459            new ECBlocks(28, new ECB(22, 45),
460                new ECB(3, 46)),
461            new ECBlocks(30, new ECB(8, 23),
462                new ECB(26, 24)),
463            new ECBlocks(30, new ECB(12, 15),
464                new ECB(28, 16))),
465        new Version(28, new int[]{6, 26, 50, 74, 98, 122},
466            new ECBlocks(30, new ECB(3, 117),
467                new ECB(10, 118)),
468            new ECBlocks(28, new ECB(3, 45),
469                new ECB(23, 46)),
470            new ECBlocks(30, new ECB(4, 24),
471                new ECB(31, 25)),
472            new ECBlocks(30, new ECB(11, 15),
473                new ECB(31, 16))),
474        new Version(29, new int[]{6, 30, 54, 78, 102, 126},
475            new ECBlocks(30, new ECB(7, 116),
476                new ECB(7, 117)),
477            new ECBlocks(28, new ECB(21, 45),
478                new ECB(7, 46)),
479            new ECBlocks(30, new ECB(1, 23),
480                new ECB(37, 24)),
481            new ECBlocks(30, new ECB(19, 15),
482                new ECB(26, 16))),
483        new Version(30, new int[]{6, 26, 52, 78, 104, 130},
484            new ECBlocks(30, new ECB(5, 115),
485                new ECB(10, 116)),
486            new ECBlocks(28, new ECB(19, 47),
487                new ECB(10, 48)),
488            new ECBlocks(30, new ECB(15, 24),
489                new ECB(25, 25)),
490            new ECBlocks(30, new ECB(23, 15),
491                new ECB(25, 16))),
492        new Version(31, new int[]{6, 30, 56, 82, 108, 134},
493            new ECBlocks(30, new ECB(13, 115),
494                new ECB(3, 116)),
495            new ECBlocks(28, new ECB(2, 46),
496                new ECB(29, 47)),
497            new ECBlocks(30, new ECB(42, 24),
498                new ECB(1, 25)),
499            new ECBlocks(30, new ECB(23, 15),
500                new ECB(28, 16))),
501        new Version(32, new int[]{6, 34, 60, 86, 112, 138},
502            new ECBlocks(30, new ECB(17, 115)),
503            new ECBlocks(28, new ECB(10, 46),
504                new ECB(23, 47)),
505            new ECBlocks(30, new ECB(10, 24),
506                new ECB(35, 25)),
507            new ECBlocks(30, new ECB(19, 15),
508                new ECB(35, 16))),
509        new Version(33, new int[]{6, 30, 58, 86, 114, 142},
510            new ECBlocks(30, new ECB(17, 115),
511                new ECB(1, 116)),
512            new ECBlocks(28, new ECB(14, 46),
513                new ECB(21, 47)),
514            new ECBlocks(30, new ECB(29, 24),
515                new ECB(19, 25)),
516            new ECBlocks(30, new ECB(11, 15),
517                new ECB(46, 16))),
518        new Version(34, new int[]{6, 34, 62, 90, 118, 146},
519            new ECBlocks(30, new ECB(13, 115),
520                new ECB(6, 116)),
521            new ECBlocks(28, new ECB(14, 46),
522                new ECB(23, 47)),
523            new ECBlocks(30, new ECB(44, 24),
524                new ECB(7, 25)),
525            new ECBlocks(30, new ECB(59, 16),
526                new ECB(1, 17))),
527        new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
528            new ECBlocks(30, new ECB(12, 121),
529                new ECB(7, 122)),
530            new ECBlocks(28, new ECB(12, 47),
531                new ECB(26, 48)),
532            new ECBlocks(30, new ECB(39, 24),
533                new ECB(14, 25)),
534            new ECBlocks(30, new ECB(22, 15),
535                new ECB(41, 16))),
536        new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
537            new ECBlocks(30, new ECB(6, 121),
538                new ECB(14, 122)),
539            new ECBlocks(28, new ECB(6, 47),
540                new ECB(34, 48)),
541            new ECBlocks(30, new ECB(46, 24),
542                new ECB(10, 25)),
543            new ECBlocks(30, new ECB(2, 15),
544                new ECB(64, 16))),
545        new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
546            new ECBlocks(30, new ECB(17, 122),
547                new ECB(4, 123)),
548            new ECBlocks(28, new ECB(29, 46),
549                new ECB(14, 47)),
550            new ECBlocks(30, new ECB(49, 24),
551                new ECB(10, 25)),
552            new ECBlocks(30, new ECB(24, 15),
553                new ECB(46, 16))),
554        new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
555            new ECBlocks(30, new ECB(4, 122),
556                new ECB(18, 123)),
557            new ECBlocks(28, new ECB(13, 46),
558                new ECB(32, 47)),
559            new ECBlocks(30, new ECB(48, 24),
560                new ECB(14, 25)),
561            new ECBlocks(30, new ECB(42, 15),
562                new ECB(32, 16))),
563        new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
564            new ECBlocks(30, new ECB(20, 117),
565                new ECB(4, 118)),
566            new ECBlocks(28, new ECB(40, 47),
567                new ECB(7, 48)),
568            new ECBlocks(30, new ECB(43, 24),
569                new ECB(22, 25)),
570            new ECBlocks(30, new ECB(10, 15),
571                new ECB(67, 16))),
572        new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
573            new ECBlocks(30, new ECB(19, 118),
574                new ECB(6, 119)),
575            new ECBlocks(28, new ECB(18, 47),
576                new ECB(31, 48)),
577            new ECBlocks(30, new ECB(34, 24),
578                new ECB(34, 25)),
579            new ECBlocks(30, new ECB(20, 15),
580                new ECB(61, 16)))
581    };
582  }
583
584}