OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 // Original code is licensed as follows: | |
7 /* | |
8 * Copyright 2011 ZXing authors | |
9 * | |
10 * Licensed under the Apache License, Version 2.0 (the "License"); | |
11 * you may not use this file except in compliance with the License. | |
12 * You may obtain a copy of the License at | |
13 * | |
14 * http://www.apache.org/licenses/LICENSE-2.0 | |
15 * | |
16 * Unless required by applicable law or agreed to in writing, software | |
17 * distributed under the License is distributed on an "AS IS" BASIS, | |
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
19 * See the License for the specific language governing permissions and | |
20 * limitations under the License. | |
21 */ | |
22 | |
23 #include "xfa/src/fxbarcode/oned/BC_OneDimWriter.h" | |
24 | |
25 #include <algorithm> | |
26 #include <memory> | |
27 | |
28 #include "xfa/src/fxbarcode/BC_Writer.h" | |
29 #include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h" | |
30 | |
31 CBC_OneDimWriter::CBC_OneDimWriter() { | |
32 m_locTextLoc = BC_TEXT_LOC_BELOWEMBED; | |
33 m_bPrintChecksum = TRUE; | |
34 m_iDataLenth = 0; | |
35 m_bCalcChecksum = FALSE; | |
36 m_pFont = NULL; | |
37 m_fFontSize = 10; | |
38 m_iFontStyle = 0; | |
39 m_fontColor = 0xff000000; | |
40 m_iContentLen = 0; | |
41 m_bLeftPadding = FALSE; | |
42 m_bRightPadding = FALSE; | |
43 m_output = NULL; | |
44 } | |
45 CBC_OneDimWriter::~CBC_OneDimWriter() { | |
46 delete m_output; | |
47 } | |
48 void CBC_OneDimWriter::SetPrintChecksum(FX_BOOL checksum) { | |
49 m_bPrintChecksum = checksum; | |
50 } | |
51 void CBC_OneDimWriter::SetDataLength(int32_t length) { | |
52 m_iDataLenth = length; | |
53 } | |
54 void CBC_OneDimWriter::SetCalcChecksum(int32_t state) { | |
55 m_bCalcChecksum = state; | |
56 } | |
57 FX_BOOL CBC_OneDimWriter::SetFont(CFX_Font* cFont) { | |
58 if (cFont == NULL) { | |
59 return FALSE; | |
60 } | |
61 m_pFont = cFont; | |
62 return TRUE; | |
63 } | |
64 void CBC_OneDimWriter::SetFontSize(FX_FLOAT size) { | |
65 m_fFontSize = size; | |
66 } | |
67 void CBC_OneDimWriter::SetFontStyle(int32_t style) { | |
68 m_iFontStyle = style; | |
69 } | |
70 void CBC_OneDimWriter::SetFontColor(FX_ARGB color) { | |
71 m_fontColor = color; | |
72 } | |
73 FX_WCHAR CBC_OneDimWriter::Upper(FX_WCHAR ch) { | |
74 if (ch >= 'a' && ch <= 'z') { | |
75 ch = ch - ('a' - 'A'); | |
76 } | |
77 return ch; | |
78 } | |
79 uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents, | |
80 BCFORMAT format, | |
81 int32_t& outWidth, | |
82 int32_t& outHeight, | |
83 int32_t hints, | |
84 int32_t& e) { | |
85 uint8_t* ret = NULL; | |
86 outHeight = 1; | |
87 if (m_Width >= 20) { | |
88 ret = Encode(contents, outWidth, e); | |
89 } else { | |
90 ret = Encode(contents, outWidth, e); | |
91 } | |
92 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
93 return ret; | |
94 } | |
95 uint8_t* CBC_OneDimWriter::Encode(const CFX_ByteString& contents, | |
96 BCFORMAT format, | |
97 int32_t& outWidth, | |
98 int32_t& outHeight, | |
99 int32_t& e) { | |
100 uint8_t* ret = Encode(contents, format, outWidth, outHeight, 0, e); | |
101 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
102 return ret; | |
103 } | |
104 int32_t CBC_OneDimWriter::AppendPattern(uint8_t* target, | |
105 int32_t pos, | |
106 const int32_t* pattern, | |
107 int32_t patternLength, | |
108 int32_t startColor, | |
109 int32_t& e) { | |
110 if (startColor != 0 && startColor != 1) { | |
111 e = BCExceptionValueMustBeEither0or1; | |
112 return 0; | |
113 } | |
114 uint8_t color = (uint8_t)startColor; | |
115 int32_t numAdded = 0; | |
116 for (int32_t i = 0; i < patternLength; i++) { | |
117 for (int32_t j = 0; j < pattern[i]; j++) { | |
118 target[pos] = color; | |
119 pos += 1; | |
120 numAdded += 1; | |
121 } | |
122 color ^= 1; | |
123 } | |
124 return numAdded; | |
125 } | |
126 void CBC_OneDimWriter::CalcTextInfo(const CFX_ByteString& text, | |
127 FXTEXT_CHARPOS* charPos, | |
128 CFX_Font* cFont, | |
129 FX_FLOAT geWidth, | |
130 int32_t fontSize, | |
131 FX_FLOAT& charsLen) { | |
132 std::unique_ptr<CFX_UnicodeEncodingEx> encoding( | |
133 FX_CreateFontEncodingEx(cFont)); | |
134 | |
135 int32_t length = text.GetLength(); | |
136 FX_DWORD* pCharCode = FX_Alloc(FX_DWORD, text.GetLength()); | |
137 FX_FLOAT charWidth = 0; | |
138 for (int32_t j = 0; j < text.GetLength(); j++) { | |
139 pCharCode[j] = encoding->CharCodeFromUnicode(text[j]); | |
140 int32_t glyp_code = encoding->GlyphFromCharCode(pCharCode[j]); | |
141 int32_t glyp_value = cFont->GetGlyphWidth(glyp_code); | |
142 FX_FLOAT temp = (FX_FLOAT)((glyp_value)*fontSize / 1000.0); | |
143 charWidth += temp; | |
144 } | |
145 charsLen = charWidth; | |
146 FX_FLOAT leftPositon = (FX_FLOAT)(geWidth - charsLen) / 2.0f; | |
147 if (leftPositon < 0 && geWidth == 0) { | |
148 leftPositon = 0; | |
149 } | |
150 FX_FLOAT penX = 0.0; | |
151 FX_FLOAT penY = | |
152 (FX_FLOAT)FXSYS_abs(cFont->GetDescent()) * (FX_FLOAT)fontSize / 1000.0f; | |
153 FX_FLOAT left = leftPositon; | |
154 FX_FLOAT top = 0.0; | |
155 charPos[0].m_OriginX = penX + left; | |
156 charPos[0].m_OriginY = penY + top; | |
157 charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[0]); | |
158 charPos[0].m_FontCharWidth = cFont->GetGlyphWidth(charPos[0].m_GlyphIndex); | |
159 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
160 charPos[0].m_ExtGID = charPos[0].m_GlyphIndex; | |
161 #endif | |
162 penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * (FX_FLOAT)fontSize / 1000.0f; | |
163 for (int32_t i = 1; i < length; i++) { | |
164 charPos[i].m_OriginX = penX + left; | |
165 charPos[i].m_OriginY = penY + top; | |
166 charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(pCharCode[i]); | |
167 charPos[i].m_FontCharWidth = cFont->GetGlyphWidth(charPos[i].m_GlyphIndex); | |
168 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
169 charPos[i].m_ExtGID = charPos[i].m_GlyphIndex; | |
170 #endif | |
171 penX += | |
172 (FX_FLOAT)(charPos[i].m_FontCharWidth) * (FX_FLOAT)fontSize / 1000.0f; | |
173 } | |
174 FX_Free(pCharCode); | |
175 } | |
176 void CBC_OneDimWriter::ShowDeviceChars(CFX_RenderDevice* device, | |
177 const CFX_Matrix* matrix, | |
178 const CFX_ByteString str, | |
179 FX_FLOAT geWidth, | |
180 FXTEXT_CHARPOS* pCharPos, | |
181 FX_FLOAT locX, | |
182 FX_FLOAT locY, | |
183 int32_t barWidth) { | |
184 int32_t iFontSize = (int32_t)fabs(m_fFontSize); | |
185 int32_t iTextHeight = iFontSize + 1; | |
186 CFX_FloatRect rect((FX_FLOAT)locX, (FX_FLOAT)locY, (FX_FLOAT)(locX + geWidth), | |
187 (FX_FLOAT)(locY + iTextHeight)); | |
188 if (geWidth != m_Width) { | |
189 rect.right -= 1; | |
190 } | |
191 matrix->TransformRect(rect); | |
192 FX_RECT re = rect.GetOutterRect(); | |
193 device->FillRect(&re, m_backgroundColor); | |
194 CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, (FX_FLOAT)locX, | |
195 (FX_FLOAT)(locY + iFontSize)); | |
196 if (matrix) { | |
197 affine_matrix.Concat(*matrix); | |
198 } | |
199 device->DrawNormalText(str.GetLength(), pCharPos, m_pFont, | |
200 CFX_GEModule::Get()->GetFontCache(), | |
201 (FX_FLOAT)iFontSize, (CFX_Matrix*)&affine_matrix, | |
202 m_fontColor, FXTEXT_CLEARTYPE); | |
203 } | |
204 void CBC_OneDimWriter::ShowBitmapChars(CFX_DIBitmap* pOutBitmap, | |
205 const CFX_ByteString str, | |
206 FX_FLOAT geWidth, | |
207 FXTEXT_CHARPOS* pCharPos, | |
208 FX_FLOAT locX, | |
209 FX_FLOAT locY, | |
210 int32_t barWidth) { | |
211 int32_t iFontSize = (int32_t)fabs(m_fFontSize); | |
212 int32_t iTextHeight = iFontSize + 1; | |
213 CFX_FxgeDevice ge; | |
214 ge.Create((int)geWidth, iTextHeight, m_colorSpace); | |
215 FX_RECT geRect(0, 0, (int)geWidth, iTextHeight); | |
216 ge.FillRect(&geRect, m_backgroundColor); | |
217 CFX_Matrix affine_matrix(1.0, 0.0, 0.0, -1.0, 0.0, (FX_FLOAT)iFontSize); | |
218 ge.DrawNormalText(str.GetLength(), pCharPos, m_pFont, | |
219 CFX_GEModule::Get()->GetFontCache(), (FX_FLOAT)iFontSize, | |
220 (CFX_Matrix*)&affine_matrix, m_fontColor, FXTEXT_CLEARTYPE); | |
221 CFX_FxgeDevice geBitmap; | |
222 geBitmap.Attach(pOutBitmap); | |
223 geBitmap.SetDIBits(ge.GetBitmap(), (int)locX, (int)locY); | |
224 } | |
225 void CBC_OneDimWriter::ShowChars(const CFX_WideStringC& contents, | |
226 CFX_DIBitmap* pOutBitmap, | |
227 CFX_RenderDevice* device, | |
228 const CFX_Matrix* matrix, | |
229 int32_t barWidth, | |
230 int32_t multiple, | |
231 int32_t& e) { | |
232 if (device == NULL && pOutBitmap == NULL) { | |
233 e = BCExceptionIllegalArgument; | |
234 return; | |
235 } | |
236 if (m_pFont == NULL) { | |
237 e = BCExceptionNullPointer; | |
238 return; | |
239 } | |
240 CFX_ByteString str = FX_UTF8Encode(contents); | |
241 int32_t iLen = str.GetLength(); | |
242 FXTEXT_CHARPOS* pCharPos = FX_Alloc(FXTEXT_CHARPOS, iLen); | |
243 FXSYS_memset(pCharPos, 0, sizeof(FXTEXT_CHARPOS) * iLen); | |
244 FX_FLOAT charsLen = 0; | |
245 FX_FLOAT geWidth = 0; | |
246 if (m_locTextLoc == BC_TEXT_LOC_ABOVEEMBED || | |
247 m_locTextLoc == BC_TEXT_LOC_BELOWEMBED) { | |
248 geWidth = 0; | |
249 } else if (m_locTextLoc == BC_TEXT_LOC_ABOVE || | |
250 m_locTextLoc == BC_TEXT_LOC_BELOW) { | |
251 geWidth = (FX_FLOAT)barWidth; | |
252 } | |
253 int32_t iFontSize = (int32_t)fabs(m_fFontSize); | |
254 int32_t iTextHeight = iFontSize + 1; | |
255 CalcTextInfo(str, pCharPos, m_pFont, geWidth, iFontSize, charsLen); | |
256 if (charsLen < 1) { | |
257 return; | |
258 } | |
259 int32_t locX = 0; | |
260 int32_t locY = 0; | |
261 switch (m_locTextLoc) { | |
262 case BC_TEXT_LOC_ABOVEEMBED: | |
263 locX = (int32_t)(barWidth - charsLen) / 2; | |
264 locY = 0; | |
265 geWidth = charsLen; | |
266 break; | |
267 case BC_TEXT_LOC_ABOVE: | |
268 locX = 0; | |
269 locY = 0; | |
270 geWidth = (FX_FLOAT)barWidth; | |
271 break; | |
272 case BC_TEXT_LOC_BELOWEMBED: | |
273 locX = (int32_t)(barWidth - charsLen) / 2; | |
274 locY = m_Height - iTextHeight; | |
275 geWidth = charsLen; | |
276 break; | |
277 case BC_TEXT_LOC_BELOW: | |
278 default: | |
279 locX = 0; | |
280 locY = m_Height - iTextHeight; | |
281 geWidth = (FX_FLOAT)barWidth; | |
282 break; | |
283 } | |
284 if (device) { | |
285 ShowDeviceChars(device, matrix, str, geWidth, pCharPos, (FX_FLOAT)locX, | |
286 (FX_FLOAT)locY, barWidth); | |
287 } else { | |
288 ShowBitmapChars(pOutBitmap, str, geWidth, pCharPos, (FX_FLOAT)locX, | |
289 (FX_FLOAT)locY, barWidth); | |
290 } | |
291 FX_Free(pCharPos); | |
292 } | |
293 void CBC_OneDimWriter::RenderBitmapResult(CFX_DIBitmap*& pOutBitmap, | |
294 const CFX_WideStringC& contents, | |
295 int32_t& e) { | |
296 if (m_output == NULL) { | |
297 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
298 } | |
299 pOutBitmap = CreateDIBitmap(m_output->GetWidth(), m_output->GetHeight()); | |
300 pOutBitmap->Clear(m_backgroundColor); | |
301 if (!pOutBitmap) { | |
302 e = BCExceptionFailToCreateBitmap; | |
303 return; | |
304 } | |
305 for (int32_t x = 0; x < m_output->GetWidth(); x++) { | |
306 for (int32_t y = 0; y < m_output->GetHeight(); y++) { | |
307 if (m_output->Get(x, y)) { | |
308 pOutBitmap->SetPixel(x, y, m_barColor); | |
309 } | |
310 } | |
311 } | |
312 int32_t i = 0; | |
313 for (; i < contents.GetLength(); i++) | |
314 if (contents.GetAt(i) != ' ') { | |
315 break; | |
316 } | |
317 if (m_locTextLoc != BC_TEXT_LOC_NONE && i < contents.GetLength()) { | |
318 ShowChars(contents, pOutBitmap, NULL, NULL, m_barWidth, m_multiple, e); | |
319 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
320 } | |
321 CFX_DIBitmap* pStretchBitmap = pOutBitmap->StretchTo(m_Width, m_Height); | |
322 if (pOutBitmap) { | |
323 delete pOutBitmap; | |
324 } | |
325 pOutBitmap = pStretchBitmap; | |
326 } | |
327 void CBC_OneDimWriter::RenderDeviceResult(CFX_RenderDevice* device, | |
328 const CFX_Matrix* matrix, | |
329 const CFX_WideStringC& contents, | |
330 int32_t& e) { | |
331 if (m_output == NULL) { | |
332 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
333 } | |
334 CFX_GraphStateData stateData; | |
335 CFX_PathData path; | |
336 path.AppendRect(0, 0, (FX_FLOAT)m_Width, (FX_FLOAT)m_Height); | |
337 device->DrawPath(&path, matrix, &stateData, m_backgroundColor, | |
338 m_backgroundColor, FXFILL_ALTERNATE); | |
339 CFX_Matrix matri(m_outputHScale, 0.0, 0.0, (FX_FLOAT)m_Height, 0.0, 0.0); | |
340 matri.Concat(*matrix); | |
341 for (int32_t x = 0; x < m_output->GetWidth(); x++) { | |
342 for (int32_t y = 0; y < m_output->GetHeight(); y++) { | |
343 CFX_PathData rect; | |
344 rect.AppendRect((FX_FLOAT)x, (FX_FLOAT)y, (FX_FLOAT)(x + 1), | |
345 (FX_FLOAT)(y + 1)); | |
346 CFX_GraphStateData stateData; | |
347 if (m_output->Get(x, y)) { | |
348 device->DrawPath(&rect, &matri, &stateData, m_barColor, 0, | |
349 FXFILL_WINDING); | |
350 } | |
351 } | |
352 } | |
353 int32_t i = 0; | |
354 for (; i < contents.GetLength(); i++) | |
355 if (contents.GetAt(i) != ' ') { | |
356 break; | |
357 } | |
358 if (m_locTextLoc != BC_TEXT_LOC_NONE && i < contents.GetLength()) { | |
359 ShowChars(contents, NULL, device, matrix, m_barWidth, m_multiple, e); | |
360 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
361 } | |
362 } | |
363 void CBC_OneDimWriter::RenderResult(const CFX_WideStringC& contents, | |
364 uint8_t* code, | |
365 int32_t codeLength, | |
366 FX_BOOL isDevice, | |
367 int32_t& e) { | |
368 if (codeLength < 1) { | |
369 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
370 } | |
371 if (m_ModuleHeight < 20.0) { | |
372 m_ModuleHeight = 20; | |
373 } | |
374 int32_t codeOldLength = codeLength; | |
375 int32_t leftPadding = 0; | |
376 int32_t rightPadding = 0; | |
377 if (m_bLeftPadding) { | |
378 leftPadding = 7; | |
379 } | |
380 if (m_bRightPadding) { | |
381 rightPadding = 7; | |
382 } | |
383 codeLength += leftPadding; | |
384 codeLength += rightPadding; | |
385 m_outputHScale = 1.0; | |
386 if (m_Width > 0) { | |
387 m_outputHScale = (FX_FLOAT)m_Width / (FX_FLOAT)codeLength; | |
388 } | |
389 if (!isDevice) { | |
390 m_outputHScale = | |
391 std::max(m_outputHScale, static_cast<FX_FLOAT>(m_ModuleWidth)); | |
392 } | |
393 FX_FLOAT dataLengthScale = 1.0; | |
394 if (m_iDataLenth > 0 && contents.GetLength() != 0) { | |
395 dataLengthScale = FX_FLOAT(contents.GetLength()) / FX_FLOAT(m_iDataLenth); | |
396 } | |
397 if (m_iDataLenth > 0 && contents.GetLength() == 0) { | |
398 dataLengthScale = FX_FLOAT(1) / FX_FLOAT(m_iDataLenth); | |
399 } | |
400 m_multiple = 1; | |
401 if (!isDevice) { | |
402 m_multiple = (int32_t)ceil(m_outputHScale * dataLengthScale); | |
403 } | |
404 int32_t outputHeight = 1; | |
405 if (!isDevice) { | |
406 if (m_Height == 0) { | |
407 outputHeight = std::max(20, m_ModuleHeight); | |
408 } else { | |
409 outputHeight = m_Height; | |
410 } | |
411 } | |
412 int32_t outputWidth = codeLength; | |
413 if (!isDevice) { | |
414 outputWidth = (int32_t)(codeLength * m_multiple / dataLengthScale); | |
415 } | |
416 m_barWidth = m_Width; | |
417 if (!isDevice) { | |
418 m_barWidth = codeLength * m_multiple; | |
419 } | |
420 m_output = new CBC_CommonBitMatrix; | |
421 m_output->Init(outputWidth, outputHeight); | |
422 int32_t outputX = leftPadding * m_multiple; | |
423 for (int32_t inputX = 0; inputX < codeOldLength; inputX++) { | |
424 if (code[inputX] == 1) { | |
425 if (outputX >= outputWidth) { | |
426 break; | |
427 } | |
428 if (outputX + m_multiple > outputWidth && outputWidth - outputX > 0) { | |
429 m_output->SetRegion(outputX, 0, outputWidth - outputX, outputHeight, e); | |
430 break; | |
431 } | |
432 m_output->SetRegion(outputX, 0, m_multiple, outputHeight, e); | |
433 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
434 } | |
435 outputX += m_multiple; | |
436 } | |
437 } | |
OLD | NEW |