git-svn-id: https://pdfsharp.svn.codeplex.com/svn@39620 56d0cb2f-6006-4f69-a5a2-94740...
[pdfsharp:pdfsharp.git] / PDFsharp / code / PdfSharp / PdfSharp.Drawing.BarCodes / Code3of9Standard.cs
1 #region PDFsharp - A .NET library for processing PDF\r
2 //\r
3 // Authors:\r
4 //   Klaus Potzesny (mailto:Klaus.Potzesny@pdfsharp.com)\r
5 //\r
6 // Copyright (c) 2005-2009 empira Software GmbH, Cologne (Germany)\r
7 //\r
8 // http://www.pdfsharp.com\r
9 // http://sourceforge.net/projects/pdfsharp\r
10 //\r
11 // Permission is hereby granted, free of charge, to any person obtaining a\r
12 // copy of this software and associated documentation files (the "Software"),\r
13 // to deal in the Software without restriction, including without limitation\r
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
15 // and/or sell copies of the Software, and to permit persons to whom the\r
16 // Software is furnished to do so, subject to the following conditions:\r
17 //\r
18 // The above copyright notice and this permission notice shall be included\r
19 // in all copies or substantial portions of the Software.\r
20 //\r
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
24 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
26 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \r
27 // DEALINGS IN THE SOFTWARE.\r
28 #endregion\r
29 \r
30 using System;\r
31 using System.Diagnostics;\r
32 \r
33 namespace PdfSharp.Drawing.BarCodes\r
34 {\r
35   /// <summary>\r
36   /// Imlpementation of the Code 3 of 9 bar code.\r
37   /// </summary>\r
38   public class Code3of9Standard : ThickThinBarCode\r
39   {\r
40     /// <summary>\r
41     /// Initializes a new instance of Standard3of9.\r
42     /// </summary>\r
43     public Code3of9Standard()\r
44       : base("", XSize.Empty, CodeDirection.LeftToRight)\r
45     {\r
46     }\r
47 \r
48     /// <summary>\r
49     /// Initializes a new instance of Standard3of9.\r
50     /// </summary>\r
51     public Code3of9Standard(string code)\r
52       : base(code, XSize.Empty, CodeDirection.LeftToRight)\r
53     {\r
54     }\r
55 \r
56     /// <summary>\r
57     /// Initializes a new instance of Standard3of9.\r
58     /// </summary>\r
59     public Code3of9Standard(string code, XSize size)\r
60       : base(code, size, CodeDirection.LeftToRight)\r
61     {\r
62     }\r
63 \r
64     /// <summary>\r
65     /// Initializes a new instance of Standard3of9.\r
66     /// </summary>\r
67     public Code3of9Standard(string code, XSize size, CodeDirection direction)\r
68       : base(code, size, direction)\r
69     {\r
70     }\r
71 \r
72     /// <summary>\r
73     /// Returns an array of size 9 that represents the thick (true) and thin (false) lines and spaces\r
74     /// representing the specified digit.\r
75     /// </summary>\r
76     /// <param name="ch">The character to represent.</param>\r
77     private static bool[] ThickThinLines(char ch)\r
78     {\r
79       return Lines["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*".IndexOf(ch)];\r
80     }\r
81     static bool[][] Lines = new bool[][]\r
82     {\r
83       // '0'\r
84       new bool[] {false, false, false, true, true, false, true, false, false},\r
85       // '1'\r
86       new bool[] {true, false, false, true, false, false, false, false, true},\r
87       // '2'\r
88       new bool[] {false, false, true, true, false, false, false, false, true},\r
89       // '3'\r
90       new bool[] {true, false, true, true, false, false, false, false, false},\r
91       // '4'\r
92       new bool[] {false, false, false, true, true, false, false, false, true},\r
93       // '5'\r
94       new bool[] {true, false, false, true, true, false, false, false, false},\r
95       // '6'\r
96       new bool[] {false, false, true, true, true, false, false, false, false},\r
97       // '7'\r
98       new bool[] {false, false, false, true, false, false, true, false, true},\r
99       // '8'\r
100       new bool[] {true, false, false, true, false, false, true, false, false},\r
101       // '9'\r
102       new bool[] {false, false, true, true, false, false, true, false, false},\r
103       // 'A'\r
104       new bool[] {true, false, false, false, false, true, false, false, true},\r
105       // 'B'\r
106       new bool[] {false, false, true, false, false, true, false, false, true},\r
107       // 'C'\r
108       new bool[] {true, false, true, false, false, true, false, false, false},\r
109       // 'D'\r
110       new bool[] {false, false, false, false, true, true, false, false, true},\r
111       // 'E'\r
112       new bool[] {true, false, false, false, true, true, false, false, false},\r
113       // 'F'\r
114       new bool[] {false, false, true, false, true, true, false, false, false},\r
115       // 'G'\r
116       new bool[] {false, false, false, false, false, true, true, false, true},\r
117       // 'H'\r
118       new bool[] {true, false, false, false, false, true, true, false, false},\r
119       // 'I'\r
120       new bool[] {false, false, true, false, false, true, true, false, false},\r
121       // 'J'\r
122       new bool[] {false, false, false, false, true, true, true, false, false},\r
123       // 'K'\r
124       new bool[] {true, false, false, false, false, false, false, true, true},\r
125       // 'L'\r
126       new bool[] {false, false, true, false, false, false, false, true, true},\r
127       // 'M'\r
128       new bool[] {true, false, true, false, false, false, false, true, false},\r
129       // 'N'\r
130       new bool[] {false, false, false, false, true, false, false, true, true},\r
131       // 'O'\r
132       new bool[] {true, false, false, false, true, false, false, true, false},\r
133       // 'P':\r
134       new bool[] {false, false, true, false, true, false, false, true, false},\r
135       // 'Q'\r
136       new bool[] {false, false, false, false, false, false, true, true, true},\r
137       // 'R'\r
138       new bool[] {true, false, false, false, false, false, true, true, false},\r
139       // 'S'\r
140       new bool[] {false, false, true, false, false, false, true, true, false},\r
141       // 'T'\r
142       new bool[] {false, false, false, false, true, false, true, true, false},\r
143       // 'U'\r
144       new bool[] {true, true, false, false, false, false, false, false, true},\r
145       // 'V'\r
146       new bool[] {false, true, true, false, false, false, false, false, true},\r
147       // 'W'\r
148       new bool[] {true, true, true, false, false, false, false, false, false},\r
149       // 'X'\r
150       new bool[] {false, true, false, false, true, false, false, false, true},\r
151       // 'Y'\r
152       new bool[] {true, true, false, false, true, false, false, false, false},\r
153       // 'Z'\r
154       new bool[] {false, true, true, false, true, false, false, false, false},\r
155       // '-'\r
156       new bool[] {false, true, false, false, false, false, true, false, true},\r
157       // '.'\r
158       new bool[] {true, true, false, false, false, false, true, false, false},\r
159       // ' '\r
160       new bool[] {false, true, true, false, false, false, true, false, false},\r
161       // '$'\r
162       new bool[] {false, true, false, true, false, true, false, false, false},\r
163       // '/'\r
164       new bool[] {false, true, false, true, false, false, false, true, false},\r
165       // '+'\r
166       new bool[] {false, true, false, false, false, true, false, true, false},\r
167       // '%'\r
168       new bool[] {false, false, false, true, false, true, false, true, false},\r
169       // '*'\r
170       new bool[] {false, true, false, false, true, false, true, false, false},\r
171    };\r
172 \r
173 \r
174     /// <summary>\r
175     /// Calculates the thick and thin line widths,\r
176     /// taking into account the required rendering size.\r
177     /// </summary>\r
178     internal override void CalcThinBarWidth(BarCodeRenderInfo info)\r
179     {\r
180       /*\r
181        * The total width is the sum of the following parts:\r
182        * Starting lines      = 3 * thick + 7 * thin\r
183        *  +\r
184        * Code Representation = (3 * thick + 7 * thin) * code.Length\r
185        *  +\r
186        * Stopping lines      =  3 * thick + 6 * thin\r
187        * \r
188        * with r = relation ( = thick / thin), this results in\r
189        * \r
190        * Total width = (13 + 6 * r + (3 * r + 7) * code.Length) * thin\r
191        */\r
192       double thinLineAmount = 13 + 6 * this.wideNarrowRatio + (3 * this.wideNarrowRatio + 7) * this.text.Length;\r
193       info.ThinBarWidth = this.Size.Width / thinLineAmount;\r
194     }\r
195 \r
196     /// <summary>\r
197     /// Checks the code to be convertible into an standard 3 of 9 bar code.\r
198     /// </summary>\r
199     /// <param name="text">The code to be checked.</param>\r
200     protected override void CheckCode(string text)\r
201     {\r
202       if (text == null)\r
203         throw new ArgumentNullException("text");\r
204 \r
205       if (text.Length == 0)\r
206         throw new ArgumentException(BcgSR.Invalid3Of9Code(text));\r
207 \r
208       foreach (char ch in text)\r
209       {\r
210         if ("0123456789ABCDEFGHIJKLMNOP'QRSTUVWXYZ-. $/+%*".IndexOf(ch) < 0)\r
211           throw new ArgumentException(BcgSR.Invalid3Of9Code(text));\r
212       }\r
213     }\r
214 \r
215     /// <summary>\r
216     /// Renders the bar code.\r
217     /// </summary>\r
218     protected internal override void Render(XGraphics gfx, XBrush brush, XFont font, XPoint position)\r
219     {\r
220       XGraphicsState state = gfx.Save();\r
221 \r
222       BarCodeRenderInfo info = new BarCodeRenderInfo(gfx, brush, font, position);\r
223       InitRendering(info);\r
224       info.CurrPosInString = 0;\r
225       //info.CurrPos = info.Center - this.size / 2;\r
226       info.CurrPos = position - CodeBase.CalcDistance(AnchorType.TopLeft, this.anchor, this.size);\r
227 \r
228       if (TurboBit)\r
229         RenderTurboBit(info, true);\r
230       RenderStart(info);\r
231       while (info.CurrPosInString < this.text.Length)\r
232       {\r
233         RenderNextChar(info);\r
234         RenderGap(info, false);\r
235       }\r
236       RenderStop(info);\r
237       if (TurboBit)\r
238         RenderTurboBit(info, false);\r
239       if (TextLocation != TextLocation.None)\r
240         RenderText(info);\r
241 \r
242       gfx.Restore(state);\r
243     }\r
244 \r
245     private void RenderNextChar(BarCodeRenderInfo info)\r
246     {\r
247       RenderChar(info, this.text[info.CurrPosInString]);\r
248       ++info.CurrPosInString;\r
249     }\r
250 \r
251     private void RenderChar(BarCodeRenderInfo info, char ch)\r
252     {\r
253       bool[] thickThinLines = ThickThinLines(ch);\r
254       int idx = 0;\r
255       while (idx < 9)\r
256       {\r
257         RenderBar(info, thickThinLines[idx]);\r
258         if (idx < 8)\r
259           RenderGap(info, thickThinLines[idx + 1]);\r
260         idx += 2;\r
261       }\r
262     }\r
263 \r
264     private void RenderStart(BarCodeRenderInfo info)\r
265     {\r
266       RenderChar(info, '*');\r
267       RenderGap(info, false);\r
268     }\r
269 \r
270     private void RenderStop(BarCodeRenderInfo info)\r
271     {\r
272       RenderChar(info, '*');\r
273     }\r
274   }\r
275 }\r