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