Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_QRCoderMaskUtil.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "barcode.h"\r
8 #include "include/BC_CommonByteMatrix.h"\r
9 #include "include/BC_QRCoderErrorCorrectionLevel.h"\r
10 #include "include/BC_QRCoder.h"\r
11 #include "include/BC_QRCoderMaskUtil.h"\r
12 CBC_QRCoderMaskUtil::CBC_QRCoderMaskUtil()\r
13 {\r
14 }\r
15 CBC_QRCoderMaskUtil::~CBC_QRCoderMaskUtil()\r
16 {\r
17 }\r
18 FX_INT32 CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(CBC_CommonByteMatrix* matrix)\r
19 {\r
20     return ApplyMaskPenaltyRule1Internal(matrix, TRUE) +\r
21            ApplyMaskPenaltyRule1Internal(matrix, FALSE);\r
22 }\r
23 FX_INT32 CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(CBC_CommonByteMatrix* matrix)\r
24 {\r
25     FX_INT32 penalty = 0;\r
26     FX_BYTE* array = matrix->GetArray();\r
27     FX_INT32 width = matrix->GetWidth();\r
28     FX_INT32 height = matrix->GetHeight();\r
29     for(FX_INT32 y = 0; y < height - 1; y++) {\r
30         for(FX_INT32 x = 0; x < width - 1; x++) {\r
31             FX_INT32 value = array[y * width + x];\r
32             if(value == array[y * width + x + 1] &&\r
33                     value == array[(y + 1) * width + x] &&\r
34                     value == array[(y + 1) * width + x + 1]) {\r
35                 penalty ++;\r
36             }\r
37         }\r
38     }\r
39     return 3 * penalty;\r
40 }\r
41 FX_INT32 CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(CBC_CommonByteMatrix* matrix)\r
42 {\r
43     FX_INT32 penalty = 0;\r
44     FX_BYTE* array = matrix->GetArray();\r
45     FX_INT32 width = matrix->GetWidth();\r
46     FX_INT32 height = matrix->GetHeight();\r
47     for (FX_INT32 y = 0; y < height; ++y) {\r
48         for (FX_INT32 x = 0; x < width; ++x) {\r
49             if (x == 0 && ((y >= 0 && y <= 6) || (y >= height - 7 && y <= height - 1))) {\r
50                 continue;\r
51             }\r
52             if (x == width - 7 && (y >= 0 && y <= 6)) {\r
53                 continue;\r
54             }\r
55             if (y == 0 && ((x >= 0 && x <= 6) || (x >= width - 7 && x <= width - 1))) {\r
56                 continue;\r
57             }\r
58             if (y == height - 7 && (x >= 0 && x <= 6)) {\r
59                 continue;\r
60             }\r
61             if (x + 6 < width &&\r
62                     array[y * width + x] == 1 &&\r
63                     array[y * width + x +  1] == 0 &&\r
64                     array[y * width + x +  2] == 1 &&\r
65                     array[y * width + x +  3] == 1 &&\r
66                     array[y * width + x +  4] == 1 &&\r
67                     array[y * width + x +  5] == 0 &&\r
68                     array[y * width + x +  6] == 1 &&\r
69                     ((x + 10 < width &&\r
70                       array[y * width + x +  7] == 0 &&\r
71                       array[y * width + x +  8] == 0 &&\r
72                       array[y * width + x +  9] == 0 &&\r
73                       array[y * width + x + 10] == 0) ||\r
74                      (x - 4 >= 0 &&\r
75                       array[y * width + x -  1] == 0 &&\r
76                       array[y * width + x -  2] == 0 &&\r
77                       array[y * width + x -  3] == 0 &&\r
78                       array[y * width + x -  4] == 0))) {\r
79                 penalty += 40;\r
80             }\r
81             if (y + 6 < height &&\r
82                     array[y * width + x] == 1  &&\r
83                     array[(y +  1) * width + x] == 0  &&\r
84                     array[(y +  2) * width + x] == 1  &&\r
85                     array[(y +  3) * width + x] == 1  &&\r
86                     array[(y +  4) * width + x] == 1  &&\r
87                     array[(y +  5) * width + x] == 0  &&\r
88                     array[(y +  6) * width + x] == 1 &&\r
89                     ((y + 10 < height &&\r
90                       array[(y +  7) * width + x] == 0 &&\r
91                       array[(y +  8) * width + x] == 0 &&\r
92                       array[(y +  9) * width + x] == 0 &&\r
93                       array[(y + 10) * width + x] == 0) ||\r
94                      (y - 4 >= 0 &&\r
95                       array[(y -  1) * width + x] == 0 &&\r
96                       array[(y -  2) * width + x] == 0 &&\r
97                       array[(y -  3) * width + x] == 0 &&\r
98                       array[(y -  4) * width + x] == 0))) {\r
99                 penalty += 40;\r
100             }\r
101         }\r
102     }\r
103     return penalty;\r
104 }\r
105 FX_INT32 CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(CBC_CommonByteMatrix* matrix)\r
106 {\r
107     FX_INT32 numDarkCells = 0;\r
108     FX_BYTE* array = matrix->GetArray();\r
109     FX_INT32 width = matrix->GetWidth();\r
110     FX_INT32 height = matrix->GetHeight();\r
111     for (FX_INT32 y = 0; y < height; ++y) {\r
112         for (FX_INT32 x = 0; x < width; ++x) {\r
113             if (array[y * width + x] == 1) {\r
114                 numDarkCells += 1;\r
115             }\r
116         }\r
117     }\r
118     FX_INT32 numTotalCells = matrix->GetHeight() * matrix->GetWidth();\r
119     double darkRatio = (double) numDarkCells / numTotalCells;\r
120     return abs( (FX_INT32) (darkRatio * 100 - 50) / 5 ) * 5 * 10;\r
121 }\r
122 FX_BOOL CBC_QRCoderMaskUtil::GetDataMaskBit(FX_INT32 maskPattern, FX_INT32 x, FX_INT32 y, FX_INT32 &e)\r
123 {\r
124     if(!CBC_QRCoder::IsValidMaskPattern(maskPattern)) {\r
125         e = (BCExceptionInvalidateMaskPattern);\r
126         BC_EXCEPTION_CHECK_ReturnValue(e, FALSE);\r
127     }\r
128     FX_INT32 intermediate = 0, temp = 0;\r
129     switch(maskPattern) {\r
130         case 0:\r
131             intermediate = (y + x) & 0x1;\r
132             break;\r
133         case 1:\r
134             intermediate = y & 0x1;\r
135             break;\r
136         case 2:\r
137             intermediate = x % 3;\r
138             break;\r
139         case 3:\r
140             intermediate = (y + x) % 3;\r
141             break;\r
142         case 4:\r
143             intermediate = ((y >> 1) + (x / 3)) & 0x1;\r
144             break;\r
145         case 5:\r
146             temp = y * x;\r
147             intermediate = (temp & 0x1) + (temp % 3);\r
148             break;\r
149         case 6:\r
150             temp = y * x;\r
151             intermediate = (((temp & 0x1) + (temp % 3)) & 0x1);\r
152             break;\r
153         case 7:\r
154             temp = y * x;\r
155             intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1);\r
156             break;\r
157         default: {\r
158                 e = BCExceptionInvalidateMaskPattern;\r
159                 BC_EXCEPTION_CHECK_ReturnValue(e, FALSE);\r
160             }\r
161     }\r
162     return intermediate == 0;\r
163 }\r
164 FX_INT32 CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1Internal(CBC_CommonByteMatrix* matrix, FX_BOOL isHorizontal)\r
165 {\r
166     FX_INT32 penalty = 0;\r
167     FX_INT32 numSameBitCells = 0;\r
168     FX_INT32 prevBit = -1;\r
169     FX_INT32 width = matrix->GetWidth();\r
170     FX_INT32 height = matrix->GetHeight();\r
171     FX_INT32 iLimit = isHorizontal ? height : width;\r
172     FX_INT32 jLimit = isHorizontal ? width : height;\r
173     FX_BYTE* array = matrix->GetArray();\r
174     for (FX_INT32 i = 0; i < iLimit; ++i) {\r
175         for (FX_INT32 j = 0; j < jLimit; ++j) {\r
176             FX_INT32 bit = isHorizontal ? array[i * width + j] : array[j * width + i];\r
177             if (bit == prevBit) {\r
178                 numSameBitCells += 1;\r
179                 if (numSameBitCells == 5) {\r
180                     penalty += 3;\r
181                 } else if (numSameBitCells > 5) {\r
182                     penalty += 1;\r
183                 }\r
184             } else {\r
185                 numSameBitCells = 1;\r
186                 prevBit = bit;\r
187             }\r
188         }\r
189         numSameBitCells = 0;\r
190     }\r
191     return penalty;\r
192 }\r