001/*
002 * Copyright 2008 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/**
021 * @author satorux@google.com (Satoru Takabayashi) - creator
022 * @author dswitkin@google.com (Daniel Switkin) - ported from C++
023 * @since 5.0.2
024 */
025public final class QRCode {
026
027  public static final int NUM_MASK_PATTERNS = 8;
028
029  private Mode mode;
030  private ErrorCorrectionLevel ecLevel;
031  private int version;
032  private int matrixWidth;
033  private int maskPattern;
034  private int numTotalBytes;
035  private int numDataBytes;
036  private int numECBytes;
037  private int numRSBlocks;
038  private ByteMatrix matrix;
039
040  public QRCode() {
041    mode = null;
042    ecLevel = null;
043    version = -1;
044    matrixWidth = -1;
045    maskPattern = -1;
046    numTotalBytes = -1;
047    numDataBytes = -1;
048    numECBytes = -1;
049    numRSBlocks = -1;
050    matrix = null;
051  }
052
053  // Mode of the QR Code.
054  public Mode getMode() {
055    return mode;
056  }
057
058  // Error correction level of the QR Code.
059  public ErrorCorrectionLevel getECLevel() {
060    return ecLevel;
061  }
062
063  // Version of the QR Code.  The bigger size, the bigger version.
064  public int getVersion() {
065    return version;
066  }
067
068  // ByteMatrix width of the QR Code.
069  public int getMatrixWidth() {
070    return matrixWidth;
071  }
072
073  // Mask pattern of the QR Code.
074  public int getMaskPattern() {
075    return maskPattern;
076  }
077
078  // Number of total bytes in the QR Code.
079  public int getNumTotalBytes() {
080    return numTotalBytes;
081  }
082
083  // Number of data bytes in the QR Code.
084  public int getNumDataBytes() {
085    return numDataBytes;
086  }
087
088  // Number of error correction bytes in the QR Code.
089  public int getNumECBytes() {
090    return numECBytes;
091  }
092
093  // Number of Reedsolomon blocks in the QR Code.
094  public int getNumRSBlocks() {
095    return numRSBlocks;
096  }
097
098  // ByteMatrix data of the QR Code.
099  public ByteMatrix getMatrix() {
100    return matrix;
101  }
102  
103
104  // Return the value of the module (cell) pointed by "x" and "y" in the matrix of the QR Code. They
105  // call cells in the matrix "modules". 1 represents a black cell, and 0 represents a white cell.
106  public int at(int x, int y) {
107    // The value must be zero or one.
108    int value = matrix.get(x, y);
109    if (!(value == 0 || value == 1)) {
110      // this is really like an assert... not sure what better exception to use?
111      throw new RuntimeException("Bad value");
112    }
113    return value;
114  }
115
116  // Checks all the member variables are set properly. Returns true on success. Otherwise, returns
117  // false.
118  public boolean isValid() {
119    return
120        // First check if all version are not uninitialized.
121        mode != null &&
122        ecLevel != null &&
123        version != -1 &&
124        matrixWidth != -1 &&
125        maskPattern != -1 &&
126        numTotalBytes != -1 &&
127        numDataBytes != -1 &&
128        numECBytes != -1 &&
129        numRSBlocks != -1 &&
130        // Then check them in other ways..
131        isValidMaskPattern(maskPattern) &&
132        numTotalBytes == numDataBytes + numECBytes &&
133        // ByteMatrix stuff.
134        matrix != null &&
135        matrixWidth == matrix.getWidth() &&
136        // See 7.3.1 of JISX0510:2004 (p.5).
137        matrix.getWidth() == matrix.getHeight(); // Must be square.
138  }
139
140  // Return debug String.
141  public String toString() {
142    StringBuffer result = new StringBuffer(200);
143    result.append("<<\n");
144    result.append(" mode: ");
145    result.append(mode);
146    result.append("\n ecLevel: ");
147    result.append(ecLevel);
148    result.append("\n version: ");
149    result.append(version);
150    result.append("\n matrixWidth: ");
151    result.append(matrixWidth);
152    result.append("\n maskPattern: ");
153    result.append(maskPattern);
154    result.append("\n numTotalBytes: ");
155    result.append(numTotalBytes);
156    result.append("\n numDataBytes: ");
157    result.append(numDataBytes);
158    result.append("\n numECBytes: ");
159    result.append(numECBytes);
160    result.append("\n numRSBlocks: ");
161    result.append(numRSBlocks);
162    if (matrix == null) {
163      result.append("\n matrix: null\n");
164    } else {
165      result.append("\n matrix:\n");
166      result.append(matrix.toString());
167    }
168    result.append(">>\n");
169    return result.toString();
170  }
171
172  public void setMode(Mode value) {
173    mode = value;
174  }
175
176  public void setECLevel(ErrorCorrectionLevel value) {
177    ecLevel = value;
178  }
179
180  public void setVersion(int value) {
181    version = value;
182  }
183
184  public void setMatrixWidth(int value) {
185    matrixWidth = value;
186  }
187
188  public void setMaskPattern(int value) {
189    maskPattern = value;
190  }
191
192  public void setNumTotalBytes(int value) {
193    numTotalBytes = value;
194  }
195
196  public void setNumDataBytes(int value) {
197    numDataBytes = value;
198  }
199
200  public void setNumECBytes(int value) {
201    numECBytes = value;
202  }
203
204  public void setNumRSBlocks(int value) {
205    numRSBlocks = value;
206  }
207
208  // This takes ownership of the 2D array.
209  public void setMatrix(ByteMatrix value) {
210    matrix = value;
211  }
212
213  // Check if "mask_pattern" is valid.
214  public static boolean isValidMaskPattern(int maskPattern) {
215    return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS;
216  }
217
218  // Return true if the all values in the matrix are binary numbers.
219  //
220  // JAVAPORT: This is going to be super expensive and unnecessary, we should not call this in
221  // production. I'm leaving it because it may be useful for testing. It should be removed entirely
222  // if ByteMatrix is changed never to contain a -1.
223  /*
224  private static boolean EverythingIsBinary(final ByteMatrix matrix) {
225    for (int y = 0; y < matrix.height(); ++y) {
226      for (int x = 0; x < matrix.width(); ++x) {
227        int value = matrix.get(y, x);
228        if (!(value == 0 || value == 1)) {
229          // Found non zero/one value.
230          return false;
231        }
232      }
233    }
234    return true;
235  }
236   */
237
238}