Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / qrcode / 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 // Original code is licensed as follows:\r
7 /*\r
8  * Copyright 2008 ZXing authors\r
9  *\r
10  * Licensed under the Apache License, Version 2.0 (the "License");\r
11  * you may not use this file except in compliance with the License.\r
12  * You may obtain a copy of the License at\r
13  *\r
14  *      http://www.apache.org/licenses/LICENSE-2.0\r
15  *\r
16  * Unless required by applicable law or agreed to in writing, software\r
17  * distributed under the License is distributed on an "AS IS" BASIS,\r
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
19  * See the License for the specific language governing permissions and\r
20  * limitations under the License.\r
21  */\r
22 \r
23 #include "../barcode.h"\r
24 #include "../common/BC_CommonByteMatrix.h"\r
25 #include "BC_QRCoderErrorCorrectionLevel.h"\r
26 #include "BC_QRCoder.h"\r
27 #include "BC_QRCoderMaskUtil.h"\r
28 CBC_QRCoderMaskUtil::CBC_QRCoderMaskUtil()\r
29 {\r
30 }\r
31 CBC_QRCoderMaskUtil::~CBC_QRCoderMaskUtil()\r
32 {\r
33 }\r
34 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(CBC_CommonByteMatrix* matrix)\r
35 {\r
36     return ApplyMaskPenaltyRule1Internal(matrix, TRUE) +\r
37            ApplyMaskPenaltyRule1Internal(matrix, FALSE);\r
38 }\r
39 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(CBC_CommonByteMatrix* matrix)\r
40 {\r
41     int32_t penalty = 0;\r
42     uint8_t* array = matrix->GetArray();\r
43     int32_t width = matrix->GetWidth();\r
44     int32_t height = matrix->GetHeight();\r
45     for(int32_t y = 0; y < height - 1; y++) {\r
46         for(int32_t x = 0; x < width - 1; x++) {\r
47             int32_t value = array[y * width + x];\r
48             if(value == array[y * width + x + 1] &&\r
49                     value == array[(y + 1) * width + x] &&\r
50                     value == array[(y + 1) * width + x + 1]) {\r
51                 penalty ++;\r
52             }\r
53         }\r
54     }\r
55     return 3 * penalty;\r
56 }\r
57 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(CBC_CommonByteMatrix* matrix)\r
58 {\r
59     int32_t penalty = 0;\r
60     uint8_t* array = matrix->GetArray();\r
61     int32_t width = matrix->GetWidth();\r
62     int32_t height = matrix->GetHeight();\r
63     for (int32_t y = 0; y < height; ++y) {\r
64         for (int32_t x = 0; x < width; ++x) {\r
65             if (x == 0 && ((y >= 0 && y <= 6) || (y >= height - 7 && y <= height - 1))) {\r
66                 continue;\r
67             }\r
68             if (x == width - 7 && (y >= 0 && y <= 6)) {\r
69                 continue;\r
70             }\r
71             if (y == 0 && ((x >= 0 && x <= 6) || (x >= width - 7 && x <= width - 1))) {\r
72                 continue;\r
73             }\r
74             if (y == height - 7 && (x >= 0 && x <= 6)) {\r
75                 continue;\r
76             }\r
77             if (x + 6 < width &&\r
78                     array[y * width + x] == 1 &&\r
79                     array[y * width + x +  1] == 0 &&\r
80                     array[y * width + x +  2] == 1 &&\r
81                     array[y * width + x +  3] == 1 &&\r
82                     array[y * width + x +  4] == 1 &&\r
83                     array[y * width + x +  5] == 0 &&\r
84                     array[y * width + x +  6] == 1 &&\r
85                     ((x + 10 < width &&\r
86                       array[y * width + x +  7] == 0 &&\r
87                       array[y * width + x +  8] == 0 &&\r
88                       array[y * width + x +  9] == 0 &&\r
89                       array[y * width + x + 10] == 0) ||\r
90                      (x - 4 >= 0 &&\r
91                       array[y * width + x -  1] == 0 &&\r
92                       array[y * width + x -  2] == 0 &&\r
93                       array[y * width + x -  3] == 0 &&\r
94                       array[y * width + x -  4] == 0))) {\r
95                 penalty += 40;\r
96             }\r
97             if (y + 6 < height &&\r
98                     array[y * width + x] == 1  &&\r
99                     array[(y +  1) * width + x] == 0  &&\r
100                     array[(y +  2) * width + x] == 1  &&\r
101                     array[(y +  3) * width + x] == 1  &&\r
102                     array[(y +  4) * width + x] == 1  &&\r
103                     array[(y +  5) * width + x] == 0  &&\r
104                     array[(y +  6) * width + x] == 1 &&\r
105                     ((y + 10 < height &&\r
106                       array[(y +  7) * width + x] == 0 &&\r
107                       array[(y +  8) * width + x] == 0 &&\r
108                       array[(y +  9) * width + x] == 0 &&\r
109                       array[(y + 10) * width + x] == 0) ||\r
110                      (y - 4 >= 0 &&\r
111                       array[(y -  1) * width + x] == 0 &&\r
112                       array[(y -  2) * width + x] == 0 &&\r
113                       array[(y -  3) * width + x] == 0 &&\r
114                       array[(y -  4) * width + x] == 0))) {\r
115                 penalty += 40;\r
116             }\r
117         }\r
118     }\r
119     return penalty;\r
120 }\r
121 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(CBC_CommonByteMatrix* matrix)\r
122 {\r
123     int32_t numDarkCells = 0;\r
124     uint8_t* array = matrix->GetArray();\r
125     int32_t width = matrix->GetWidth();\r
126     int32_t height = matrix->GetHeight();\r
127     for (int32_t y = 0; y < height; ++y) {\r
128         for (int32_t x = 0; x < width; ++x) {\r
129             if (array[y * width + x] == 1) {\r
130                 numDarkCells += 1;\r
131             }\r
132         }\r
133     }\r
134     int32_t numTotalCells = matrix->GetHeight() * matrix->GetWidth();\r
135     double darkRatio = (double) numDarkCells / numTotalCells;\r
136     return abs( (int32_t) (darkRatio * 100 - 50) / 5 ) * 5 * 10;\r
137 }\r
138 FX_BOOL CBC_QRCoderMaskUtil::GetDataMaskBit(int32_t maskPattern, int32_t x, int32_t y, int32_t &e)\r
139 {\r
140     if(!CBC_QRCoder::IsValidMaskPattern(maskPattern)) {\r
141         e = (BCExceptionInvalidateMaskPattern);\r
142         BC_EXCEPTION_CHECK_ReturnValue(e, FALSE);\r
143     }\r
144     int32_t intermediate = 0, temp = 0;\r
145     switch(maskPattern) {\r
146         case 0:\r
147             intermediate = (y + x) & 0x1;\r
148             break;\r
149         case 1:\r
150             intermediate = y & 0x1;\r
151             break;\r
152         case 2:\r
153             intermediate = x % 3;\r
154             break;\r
155         case 3:\r
156             intermediate = (y + x) % 3;\r
157             break;\r
158         case 4:\r
159             intermediate = ((y >> 1) + (x / 3)) & 0x1;\r
160             break;\r
161         case 5:\r
162             temp = y * x;\r
163             intermediate = (temp & 0x1) + (temp % 3);\r
164             break;\r
165         case 6:\r
166             temp = y * x;\r
167             intermediate = (((temp & 0x1) + (temp % 3)) & 0x1);\r
168             break;\r
169         case 7:\r
170             temp = y * x;\r
171             intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1);\r
172             break;\r
173         default: {\r
174                 e = BCExceptionInvalidateMaskPattern;\r
175                 BC_EXCEPTION_CHECK_ReturnValue(e, FALSE);\r
176             }\r
177     }\r
178     return intermediate == 0;\r
179 }\r
180 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1Internal(CBC_CommonByteMatrix* matrix, FX_BOOL isHorizontal)\r
181 {\r
182     int32_t penalty = 0;\r
183     int32_t numSameBitCells = 0;\r
184     int32_t prevBit = -1;\r
185     int32_t width = matrix->GetWidth();\r
186     int32_t height = matrix->GetHeight();\r
187     int32_t iLimit = isHorizontal ? height : width;\r
188     int32_t jLimit = isHorizontal ? width : height;\r
189     uint8_t* array = matrix->GetArray();\r
190     for (int32_t i = 0; i < iLimit; ++i) {\r
191         for (int32_t j = 0; j < jLimit; ++j) {\r
192             int32_t bit = isHorizontal ? array[i * width + j] : array[j * width + i];\r
193             if (bit == prevBit) {\r
194                 numSameBitCells += 1;\r
195                 if (numSameBitCells == 5) {\r
196                     penalty += 3;\r
197                 } else if (numSameBitCells > 5) {\r
198                     penalty += 1;\r
199                 }\r
200             } else {\r
201                 numSameBitCells = 1;\r
202                 prevBit = bit;\r
203             }\r
204         }\r
205         numSameBitCells = 0;\r
206     }\r
207     return penalty;\r
208 }\r