/*
 * Copyright 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.zxing.client.android;

import com.google.zxing.MonochromeBitmapSource;
import com.google.zxing.ReaderException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.detector.AlignmentPattern;
import com.google.zxing.qrcode.detector.FinderPattern;
import com.google.zxing.qrcode.detector.GridSampler;

import android.graphics.Matrix;

/**
 * Implementation based on Android's
 * {@link Matrix#setPolyToPoly(float[], int, float[], int, int)}
 * class, which should offer faster performance for these matrix
 * operations.
 * 
 * @author srowen@google.com (Sean Owen)
 */
public final class AndroidGraphicsGridSampler extends GridSampler {

  @Override
  protected BitMatrix sampleGrid(MonochromeBitmapSource image,
                                 FinderPattern topLeft,
                                 FinderPattern topRight,
                                 FinderPattern bottomLeft,
                                 AlignmentPattern alignmentPattern,
                                 int dimension) throws ReaderException {
    float dimMinusThree = (float) dimension - 3.5f;
    float bottomRightX, bottomRightY;
    float sourceBottomRightX, sourceBottomRightY;
    if (alignmentPattern != null) {
      bottomRightX = alignmentPattern.getX();
      bottomRightY = alignmentPattern.getY();
      sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
    } else {
      // Don't have an alignment pattern, just make up the bottom-right point
      bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();
      bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();
      sourceBottomRightX = sourceBottomRightY = dimMinusThree;
    }

    Matrix transformMatrix = new Matrix();
    boolean succeeded = transformMatrix.setPolyToPoly(
      new float[] {
        topLeft.getX(),
        topLeft.getY(),
        topRight.getX(),
        topRight.getY(),
        bottomLeft.getX(),
        bottomLeft.getY(),
        bottomRightX,
        bottomRightY
      },
      0,
      new float[] {
        3.5f,
        3.5f,
        dimMinusThree,
        3.5f,
        3.5f,
        dimMinusThree,
        sourceBottomRightX,
        sourceBottomRightY,
      },
      0,
      4
    );
    if (!succeeded) {
      throw new ReaderException("Could not establish transformation matrix");
    }

    BitMatrix bits = new BitMatrix(dimension);
    float[] points = new float[dimension << 1];
    for (int i = 0; i < dimension; i++) {
      int max = points.length;
      float iValue = (float) i + 0.5f;
      for (int j = 0; j < max; j += 2) {
        points[j] = (float) (j >> 1) + 0.5f;
        points[j + 1] = iValue;
      }
      transformMatrix.mapPoints(points);
      // Quick check to see if points transformed to something inside the image;
      // sufficent to check the endpoints
      checkEndpoint(image, points);
      for (int j = 0; j < max; j += 2) {
        if (image.isBlack((int) points[j], (int) points[j + 1])) {
          // Black(-ish) pixel
          bits.set(i, j >> 1);
        }
      }
    }
    return bits;
  }

}

@@ -632,16 +632,48 @@
 droid;%0A%0A
+import android.graphics.Matrix;%0A
 import c
@@ -823,181 +823,26 @@
 ing.
-qrcode.detector.AlignmentPattern;%0Aimport com.google.zxing.qrcode.detector.FinderPattern;%0Aimport com.google.zxing.qrcode.detector.GridSampler;%0A%0Aimport android.graphics.Matrix
+common.GridSampler
 ;%0A%0A/
@@ -1163,16 +1163,13 @@
 %0A  p
-rotected
+ublic
  Bit
@@ -1250,32 +1250,21 @@
     
-   FinderPattern topLeft
+int dimension
 ,%0A  
@@ -1295,33 +1295,32 @@
     
- 
-  FinderPattern topRight
+float p1ToX, float p1ToY
 ,%0A  
@@ -1351,35 +1351,32 @@
     
- 
-  FinderPattern bottomLeft
+float p2ToX, float p2ToY
 ,%0A  
@@ -1407,1286 +1407,631 @@
     
-   AlignmentPattern alignmentPattern,%0A                                 int dimension) throws ReaderException %7B%0A    float dimMinusThree = (float) dimension - 3.5f;%0A    float bottomRightX, bottomRightY;%0A    float sourceBottomRightX, sourceBottomRightY;%0A    if (alignmentPattern != null) %7B%0A      bottomRightX = alignmentPattern.getX();%0A      bottomRightY = alignmentPattern.getY();%0A      sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;%0A    %7D else %7B%0A      // Don't have an alignment pattern, just make up the bottom-right point%0A      bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();%0A      bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();%0A      sourceBottomRightX = sourceBottomRightY = dimMinusThree;%0A    %7D%0A%0A    Matrix transformMatrix = new Matrix();%0A    boolean succeeded = transformMatrix.setPolyToPoly(%0A      new float%5B%5D %7B%0A        topLeft.getX(),%0A        topLeft.getY(),%0A        topRight.getX(),%0A        topRight.getY(),%0A        bottomLeft.getX(),%0A        bottomLeft.getY(),%0A        bottomRightX,%0A        bottomRightY%0A      %7D,%0A      0,%0A      new float%5B%5D %7B%0A        3.5f,%0A        3.5f,%0A        dimMinusThree,%0A        3.5f,%0A        3.5f,%0A        dimMinusThree,%0A        sourceBottomRightX,%0A        sourceBottomRightY,%0A     
+float p3ToX, float p3ToY,%0A                              float p4ToX, float p4ToY,%0A                              float p1FromX, float p1FromY,%0A                              float p2FromX, float p2FromY,%0A                              float p3FromX, float p3FromY,%0A                              float p4FromX, float p4FromY) throws ReaderException %7B%0A%0A    Matrix transformMatrix = new Matrix();%0A    boolean succeeded = transformMatrix.setPolyToPoly(%0A      new float%5B%5D %7B p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY %7D,%0A      0,%0A      new float%5B%5D %7B p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY
  %7D,%0A

Move GridSampler into common package and refactor to ready it for use with Data Matrix