C++ port: add decode hints system
[zxing.git] / cpp / core / src / zxing / datamatrix / Version.cpp
1 /*
2  *  Version.cpp
3  *  zxing
4  *
5  *  Created by Luiz Silva on 09/02/2010.
6  *  Copyright 2010 ZXing authors All rights reserved.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <zxing/datamatrix/Version.h>
22 #include <limits>
23 #include <iostream>
24
25 namespace zxing {
26 namespace datamatrix {
27 using namespace std;
28
29 ECB::ECB(int count, int dataCodewords) :
30     count_(count), dataCodewords_(dataCodewords) {
31 }
32
33 int ECB::getCount() {
34   return count_;
35 }
36
37 int ECB::getDataCodewords() {
38   return dataCodewords_;
39 }
40
41 ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks) :
42     ecCodewords_(ecCodewords), ecBlocks_(1, ecBlocks) {
43 }
44
45 ECBlocks::ECBlocks(int ecCodewords, ECB *ecBlocks1, ECB *ecBlocks2) :
46     ecCodewords_(ecCodewords), ecBlocks_(1, ecBlocks1) {
47   ecBlocks_.push_back(ecBlocks2);
48 }
49
50 int ECBlocks::getECCodewords() {
51   return ecCodewords_;
52 }
53
54 std::vector<ECB*>& ECBlocks::getECBlocks() {
55   return ecBlocks_;
56 }
57
58 ECBlocks::~ECBlocks() {
59   for (size_t i = 0; i < ecBlocks_.size(); i++) {
60     delete ecBlocks_[i];
61   }
62 }
63
64 vector<Ref<Version> > Version::VERSIONS;
65 static int N_VERSIONS = Version::buildVersions();
66
67 Version::Version(int versionNumber, int symbolSizeRows, int symbolSizeColumns, int dataRegionSizeRows,
68                 int dataRegionSizeColumns, ECBlocks* ecBlocks) : versionNumber_(versionNumber), 
69                 symbolSizeRows_(symbolSizeRows), symbolSizeColumns_(symbolSizeColumns), 
70                 dataRegionSizeRows_(dataRegionSizeRows), dataRegionSizeColumns_(dataRegionSizeColumns), 
71                 ecBlocks_(ecBlocks), totalCodewords_(0) {
72     // Calculate the total number of codewords
73     int total = 0;
74     int ecCodewords = ecBlocks_->getECCodewords();
75     vector<ECB*> &ecbArray = ecBlocks_->getECBlocks();
76     for (unsigned int i = 0; i < ecbArray.size(); i++) {
77       ECB *ecBlock = ecbArray[i];
78       total += ecBlock->getCount() * (ecBlock->getDataCodewords() + ecCodewords);
79     }
80     totalCodewords_ = total;
81 }
82
83 Version::~Version() {
84     delete ecBlocks_;
85 }
86
87 int Version::getVersionNumber() {
88   return versionNumber_;
89 }
90
91 int Version::getSymbolSizeRows() {
92   return symbolSizeRows_;
93 }
94   
95 int Version::getSymbolSizeColumns() {
96   return symbolSizeColumns_;
97 }
98
99 int Version::getDataRegionSizeRows() {
100   return dataRegionSizeRows_;
101 }
102   
103 int Version::getDataRegionSizeColumns() {
104   return dataRegionSizeColumns_;
105 }
106   
107 int Version::getTotalCodewords() {
108   return totalCodewords_;
109 }
110
111 ECBlocks* Version::getECBlocks() {
112   return ecBlocks_;
113 }
114   
115 Ref<Version> Version::getVersionForDimensions(int numRows, int numColumns) {
116     if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0) {
117       throw ReaderException("Number of rows and columns must be even");
118     }
119     
120     // TODO(bbrown): This is doing a linear search through the array of versions.
121     // If we interleave the rectangular versions with the square versions we could
122     // do a binary search.
123     for (int i = 0; i < N_VERSIONS; ++i){
124       Ref<Version> version(VERSIONS[i]);
125       if (version->getSymbolSizeRows() == numRows && version->getSymbolSizeColumns() == numColumns) {
126         return version;
127       }
128     }
129     throw ReaderException("Error version not found");
130   }
131
132 /**
133  * See ISO 16022:2006 5.5.1 Table 7
134  */
135 int Version::buildVersions() {
136   VERSIONS.push_back(Ref<Version>(new Version(1, 10, 10, 8, 8,
137                                                   new ECBlocks(5, new ECB(1, 3)))));
138   VERSIONS.push_back(Ref<Version>(new Version(2, 12, 12, 10, 10,
139                                                   new ECBlocks(7, new ECB(1, 5)))));
140   VERSIONS.push_back(Ref<Version>(new Version(3, 14, 14, 12, 12,
141                                                   new ECBlocks(10, new ECB(1, 8)))));
142   VERSIONS.push_back(Ref<Version>(new Version(4, 16, 16, 14, 14,
143                                                   new ECBlocks(12, new ECB(1, 12)))));
144   VERSIONS.push_back(Ref<Version>(new Version(5, 18, 18, 16, 16,
145                                                   new ECBlocks(14, new ECB(1, 18)))));
146   VERSIONS.push_back(Ref<Version>(new Version(6, 20, 20, 18, 18,
147                                                   new ECBlocks(18, new ECB(1, 22)))));
148   VERSIONS.push_back(Ref<Version>(new Version(7, 22, 22, 20, 20,
149                                                   new ECBlocks(20, new ECB(1, 30)))));
150   VERSIONS.push_back(Ref<Version>(new Version(8, 24, 24, 22, 22,
151                                                   new ECBlocks(24, new ECB(1, 36)))));
152   VERSIONS.push_back(Ref<Version>(new Version(9, 26, 26, 24, 24,
153                                                   new ECBlocks(28, new ECB(1, 44)))));
154   VERSIONS.push_back(Ref<Version>(new Version(10, 32, 32, 14, 14,
155                                                   new ECBlocks(36, new ECB(1, 62)))));
156   VERSIONS.push_back(Ref<Version>(new Version(11, 36, 36, 16, 16,
157                                                   new ECBlocks(42, new ECB(1, 86)))));
158   VERSIONS.push_back(Ref<Version>(new Version(12, 40, 40, 18, 18,
159                                                   new ECBlocks(48, new ECB(1, 114)))));
160   VERSIONS.push_back(Ref<Version>(new Version(13, 44, 44, 20, 20,
161                                                   new ECBlocks(56, new ECB(1, 144)))));
162   VERSIONS.push_back(Ref<Version>(new Version(14, 48, 48, 22, 22,
163                                                   new ECBlocks(68, new ECB(1, 174)))));
164   VERSIONS.push_back(Ref<Version>(new Version(15, 52, 52, 24, 24,
165                                                   new ECBlocks(42, new ECB(2, 102)))));
166   VERSIONS.push_back(Ref<Version>(new Version(16, 64, 64, 14, 14,
167                                                   new ECBlocks(56, new ECB(2, 140)))));
168   VERSIONS.push_back(Ref<Version>(new Version(17, 72, 72, 16, 16,
169                                                   new ECBlocks(36, new ECB(4, 92)))));
170   VERSIONS.push_back(Ref<Version>(new  Version(18, 80, 80, 18, 18,
171                                                   new ECBlocks(48, new ECB(4, 114)))));
172   VERSIONS.push_back(Ref<Version>(new Version(19, 88, 88, 20, 20,
173                                                   new ECBlocks(56, new ECB(4, 144)))));
174   VERSIONS.push_back(Ref<Version>(new Version(20, 96, 96, 22, 22,
175                                                   new ECBlocks(68, new ECB(4, 174)))));
176   VERSIONS.push_back(Ref<Version>(new Version(21, 104, 104, 24, 24,
177                                                   new ECBlocks(56, new ECB(6, 136)))));
178   VERSIONS.push_back(Ref<Version>(new Version(22, 120, 120, 18, 18,
179                                                   new ECBlocks(68, new ECB(6, 175)))));
180   VERSIONS.push_back(Ref<Version>(new Version(23, 132, 132, 20, 20,
181                                                   new ECBlocks(62, new ECB(8, 163)))));
182   VERSIONS.push_back(Ref<Version>(new Version(24, 144, 144, 22, 22,
183                                                   new ECBlocks(62, new ECB(8, 156), new ECB(2, 155)))));
184   VERSIONS.push_back(Ref<Version>(new Version(25, 8, 18, 6, 16,
185                                                   new ECBlocks(7, new ECB(1, 5)))));
186   VERSIONS.push_back(Ref<Version>(new Version(26, 8, 32, 6, 14,
187                                                   new ECBlocks(11, new ECB(1, 10)))));
188   VERSIONS.push_back(Ref<Version>(new Version(27, 12, 26, 10, 24,
189                                                       new ECBlocks(14, new ECB(1, 16)))));
190   VERSIONS.push_back(Ref<Version>(new Version(28, 12, 36, 10, 16,
191                                                       new ECBlocks(18, new ECB(1, 22)))));
192   VERSIONS.push_back(Ref<Version>(new Version(29, 16, 36, 10, 16,
193                                                       new ECBlocks(24, new ECB(1, 32)))));
194   VERSIONS.push_back(Ref<Version>(new Version(30, 16, 48, 14, 22,
195                                                       new ECBlocks(28, new ECB(1, 49)))));
196   return VERSIONS.size();
197 }
198 }
199 }