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 * <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which
021 * data can be encoded to bits in the QR code standard.</p>
022 *
023 * @author Sean Owen
024 * @since 5.0.2
025 */
026public final class Mode {
027
028  // No, we can't use an enum here. J2ME doesn't support it.
029
030  public static final Mode TERMINATOR = new Mode(new int[]{0, 0, 0}, 0x00, "TERMINATOR"); // Not really a mode...
031  public static final Mode NUMERIC = new Mode(new int[]{10, 12, 14}, 0x01, "NUMERIC");
032  public static final Mode ALPHANUMERIC = new Mode(new int[]{9, 11, 13}, 0x02, "ALPHANUMERIC");
033  public static final Mode STRUCTURED_APPEND = new Mode(new int[]{0, 0, 0}, 0x03, "STRUCTURED_APPEND"); // Not supported
034  public static final Mode BYTE = new Mode(new int[]{8, 16, 16}, 0x04, "BYTE");
035  public static final Mode ECI = new Mode(null, 0x07, "ECI"); // character counts don't apply
036  public static final Mode KANJI = new Mode(new int[]{8, 10, 12}, 0x08, "KANJI");
037  public static final Mode FNC1_FIRST_POSITION = new Mode(null, 0x05, "FNC1_FIRST_POSITION");
038  public static final Mode FNC1_SECOND_POSITION = new Mode(null, 0x09, "FNC1_SECOND_POSITION");
039
040  private final int[] characterCountBitsForVersions;
041  private final int bits;
042  private final String name;
043
044  private Mode(int[] characterCountBitsForVersions, int bits, String name) {
045    this.characterCountBitsForVersions = characterCountBitsForVersions;
046    this.bits = bits;
047    this.name = name;
048  }
049
050  /**
051   * @param bits four bits encoding a QR Code data mode
052   * @return {@link Mode} encoded by these bits
053   * @throws IllegalArgumentException if bits do not correspond to a known mode
054   */
055  public static Mode forBits(int bits) {
056    switch (bits) {
057      case 0x0:
058        return TERMINATOR;
059      case 0x1:
060        return NUMERIC;
061      case 0x2:
062        return ALPHANUMERIC;
063      case 0x3:
064        return STRUCTURED_APPEND;
065      case 0x4:
066        return BYTE;
067      case 0x5:
068        return FNC1_FIRST_POSITION;
069      case 0x7:
070        return ECI;
071      case 0x8:
072        return KANJI;
073      case 0x9:
074        return FNC1_SECOND_POSITION;
075      default:
076        throw new IllegalArgumentException();
077    }
078  }
079
080  /**
081   * @param version version in question
082   * @return number of bits used, in this QR Code symbol {@link Version}, to encode the
083   *         count of characters that will follow encoded in this {@link Mode}
084   */
085  public int getCharacterCountBits(Version version) {
086    if (characterCountBitsForVersions == null) {
087      throw new IllegalArgumentException("Character count doesn't apply to this mode");
088    }
089    int number = version.getVersionNumber();
090    int offset;
091    if (number <= 9) {
092      offset = 0;
093    } else if (number <= 26) {
094      offset = 1;
095    } else {
096      offset = 2;
097    }
098    return characterCountBitsForVersions[offset];
099  }
100
101  public int getBits() {
102    return bits;
103  }
104
105  public String getName() {
106    return name;
107  }
108
109  public String toString() {
110    return name;
111  }
112
113}