using FastReport.Utils; using System; using System.Collections.Generic; using System.Drawing; using System.Text; using System.Text.RegularExpressions; namespace FastReport.Barcode { /// /// Base methods for GS1 DataBar barcodes. /// public class BarcodeGS1Base : LinearBarcodeBase { protected List EncodedData { get; set; } /// /// Routine to generate widths for GS1 elements for a given value. /// /// Required value. /// Number of modules. /// Elements in a set (GS1 omni based and Expanded = 4; GS1 Limited = 7). /// Maximum module width of an element. /// False will skip patterns without a one module wide element. /// Element widths protected List GetGS1Widths(int val, int n, int elements, int maxWidth, int noNarrow) { int elmWidth; int subVal, lessVal; int narrowMask = 0; List widths = new List(); for (int bar = 0; bar < elements - 1; bar++) { for (elmWidth = 1, narrowMask |= (1 << bar); ; elmWidth++, narrowMask &= ~(1 << bar)) { // Get all combinations subVal = Combins(n - elmWidth - 1, elements - bar - 2); //Less combinations with no single-module element if ((noNarrow == 0) && (narrowMask == 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) { subVal -= Combins(n - elmWidth - (elements - bar), elements - bar - 2); } // Less combinations with elements > maxVal if (elements - bar - 1 > 1) { lessVal = 0; for (int mxwElement = n - elmWidth - (elements - bar - 2); mxwElement > maxWidth; mxwElement--) { lessVal += Combins(n - elmWidth - mxwElement - 1, elements - bar - 3); } subVal -= lessVal * (elements - 1 - bar); } else if (n - elmWidth > maxWidth) { subVal--; } val -= subVal; if (val < 0) break; } val += subVal; n -= elmWidth; widths.Add(elmWidth); } widths.Add(n); return widths; } /// /// /// /// /// /// Returns the number of Combinations of r selected from n. private int Combins(int n, int r) { int i, j; int maxDenom, minDenom; int val; if (n - r > r) { minDenom = r; maxDenom = n - r; } else { minDenom = n - r; maxDenom = r; } val = 1; j = 1; for (i = n; i > maxDenom; i--) { val *= i; if (j <= minDenom) { val /= j; j++; } } for (; j <= minDenom; j++) { val /= j; } return (val); } /// /// Drawing lines of strokes /// /// Encoded data in width strokes; For separate line, these are colored strokes, any value that is not equal to zero is black. /// /// Scale size. /// Use left of rectangle for to set start position x, top for top pos y, bottom for bottom pos y of strokes. /// Flag for reversing color by default first strokes white, disabled for separate line. /// Flag separete line protected void DrawLineBars(string data, IGraphics g, float zoom, RectangleF rect, bool reversColor, bool separatorLine = false) { using (Pen pen = new Pen(Color)) { float currentWidth = rect.Left; for (int x = 0; x < data.Length; x++) { float heightStart = rect.Top; float heightEnd = rect.Bottom; float width = WideBarRatio; if (!separatorLine) width = (data[x] - '0') * WideBarRatio; width *= zoom; heightStart *= zoom; heightEnd *= zoom; pen.Width = width; if (reversColor) pen.Color = Color.Black; else pen.Color = Color.Transparent; if (separatorLine) { if (data[x] != '0') pen.Color = Color.Black; } else { if ((x % 2 != 0 && !reversColor)) pen.Color = Color.Black; if ((x % 2 != 0 && reversColor)) pen.Color = Color.Transparent; } g.DrawLine(pen, currentWidth + width / 2, barArea.Top * zoom + heightStart, currentWidth + width / 2, barArea.Top * zoom + heightEnd); currentWidth += width; } } } /// public override string GetDefaultValue() { return "(01)0000123456789"; } } /// /// Generates the GS1 DataBar Omnidirectional barcode. /// public class BarcodeGS1Omnidirectional : BarcodeGS1Base { /// /// Get value for encoding. /// /// Data /// protected long GetValue(string data) { long result; string prefix = ""; int startPrefix = data.IndexOf('('); int endPrefix = data.IndexOf(')'); if (startPrefix >= 0 && endPrefix > 0) { prefix = data.Substring(startPrefix, endPrefix + 1); data = data.Replace(prefix, ""); } if(data.Length > 13) data = data.Remove(13, 1); if (!long.TryParse(data, out result) || data.Length != 13 || result < 0) throw new FormatException(Res.Get("Messages,InvalidBarcode2")); if (prefix == "") prefix = "(01)"; this.text = prefix + CheckSumModulo10(data); return result + 10000000000000; } private int[] ChecksumWeight = { 1, 3, 9, 27, 2, 6, 18, 54, 4, 12, 36, 29, 8, 24, 72, 58, 16, 48, 65, 37, 32, 17, 51, 74, 64, 34, 23, 69, 49, 68, 46, 59 }; private int[] FinderPattern = { 3, 8, 2, 1, 1, 3, 5, 5, 1, 1, 3, 3, 7, 1, 1, 3, 1, 9, 1, 1, 2, 7, 4, 1, 1, 2, 5, 6, 1, 1, 2, 3, 8, 1, 1, 1, 5, 7, 1, 1, 1, 3, 9, 1, 1 }; private int[] ModulesOdd = { 12, 10, 8, 6, 4, 5, 7, 9, 11 }; private int[] ModulesEven = { 4, 6, 8, 10, 12, 10, 8, 6, 4 }; private int[] WidthsOdd = { 8, 6, 4, 3, 1, 2, 4, 6, 8 }; private int[] WidthsEven = { 1, 3, 5, 6, 8, 7, 5, 3, 1 }; private int[] GSums = { 0, 161, 961, 2015, 2715, 0, 336, 1036, 1516 }; private int[] TList = { 1, 10, 34, 70, 126, 4, 20, 48, 81 }; internal override string GetPattern() { EncodedData = new List(); int[] dataGroup = new int[4]; int[] v_odd = new int[4]; int[] v_even = new int[4]; long value = GetValue(text); long left = value / 4537077; long right = value % 4537077; int data1 = (int)(left / 1597); int data2 = (int)(left % 1597); int data3 = (int)(right / 1597); int data4 = (int)(right % 1597); if ((data1 >= 0) && (data1 <= 160)) { dataGroup[0] = 0; } if ((data1 >= 161) && (data1 <= 960)) { dataGroup[0] = 1; } if ((data1 >= 961) && (data1 <= 2014)) { dataGroup[0] = 2; } if ((data1 >= 2015) && (data1 <= 2714)) { dataGroup[0] = 3; } if ((data1 >= 2715) && (data1 <= 2840)) { dataGroup[0] = 4; } if ((data2 >= 0) && (data2 <= 335)) { dataGroup[1] = 5; } if ((data2 >= 336) && (data2 <= 1035)) { dataGroup[1] = 6; } if ((data2 >= 1036) && (data2 <= 1515)) { dataGroup[1] = 7; } if ((data2 >= 1516) && (data2 <= 1596)) { dataGroup[1] = 8; } if ((data4 >= 0) && (data4 <= 335)) { dataGroup[3] = 5; } if ((data4 >= 336) && (data4 <= 1035)) { dataGroup[3] = 6; } if ((data4 >= 1036) && (data4 <= 1515)) { dataGroup[3] = 7; } if ((data4 >= 1516) && (data4 <= 1596)) { dataGroup[3] = 8; } if ((data3 >= 0) && (data3 <= 160)) { dataGroup[2] = 0; } if ((data3 >= 161) && (data3 <= 960)) { dataGroup[2] = 1; } if ((data3 >= 961) && (data3 <= 2014)) { dataGroup[2] = 2; } if ((data3 >= 2015) && (data3 <= 2714)) { dataGroup[2] = 3; } if ((data3 >= 2715) && (data3 <= 2840)) { dataGroup[2] = 4; } v_odd[0] = (data1 - GSums[dataGroup[0]]) / TList[dataGroup[0]]; v_even[0] = (data1 - GSums[dataGroup[0]]) % TList[dataGroup[0]]; v_odd[1] = (data2 - GSums[dataGroup[1]]) % TList[dataGroup[1]]; v_even[1] = (data2 - GSums[dataGroup[1]]) / TList[dataGroup[1]]; v_odd[3] = (data4 - GSums[dataGroup[3]]) % TList[dataGroup[3]]; v_even[3] = (data4 - GSums[dataGroup[3]]) / TList[dataGroup[3]]; v_odd[2] = (data3 - GSums[dataGroup[2]]) / TList[dataGroup[2]]; v_even[2] = (data3 - GSums[dataGroup[2]]) % TList[dataGroup[2]]; int[,] data_widths = new int[8, 4]; /* Use GS1 subset width algorithm */ for (int i = 0; i < 4; i++) { if ((i == 0) || (i == 2)) { List widths; widths = GetGS1Widths(v_odd[i], ModulesOdd[dataGroup[i]], 4, WidthsOdd[dataGroup[i]], 1); data_widths[0, i] = widths[0]; data_widths[2, i] = widths[1]; data_widths[4, i] = widths[2]; data_widths[6, i] = widths[3]; widths = GetGS1Widths(v_even[i], ModulesEven[dataGroup[i]], 4, WidthsEven[dataGroup[i]], 0); data_widths[1, i] = widths[0]; data_widths[3, i] = widths[1]; data_widths[5, i] = widths[2]; data_widths[7, i] = widths[3]; } else { List widths; widths = GetGS1Widths(v_odd[i], ModulesOdd[dataGroup[i]], 4, WidthsOdd[dataGroup[i]], 0); data_widths[0, i] = widths[0]; data_widths[2, i] = widths[1]; data_widths[4, i] = widths[2]; data_widths[6, i] = widths[3]; widths = GetGS1Widths(v_even[i], ModulesEven[dataGroup[i]], 4, WidthsEven[dataGroup[i]], 1); data_widths[1, i] = widths[0]; data_widths[3, i] = widths[1]; data_widths[5, i] = widths[2]; data_widths[7, i] = widths[3]; } } // Calculate the checksum int checksum = 0; for (int i = 0; i < 8; i++) { checksum += ChecksumWeight[i] * data_widths[i, 0]; checksum += ChecksumWeight[i + 8] * data_widths[i, 1]; checksum += ChecksumWeight[i + 16] * data_widths[i, 2]; checksum += ChecksumWeight[i + 24] * data_widths[i, 3]; } checksum %= 79; // Calculate the two check characters if (checksum >= 8) { checksum++; } if (checksum >= 72) { checksum++; } int c_left = checksum / 9; int c_right = checksum % 9; int[] barWeights = new int[46]; // Put element widths together barWeights[0] = 1; barWeights[1] = 1; barWeights[44] = 1; barWeights[45] = 1; for (int i = 0; i < 8; i++) { barWeights[i + 2] = data_widths[i, 0]; barWeights[i + 15] = data_widths[7 - i, 1]; barWeights[i + 23] = data_widths[i, 3]; barWeights[i + 36] = data_widths[7 - i, 2]; } for (int i = 0; i < 5; i++) { barWeights[i + 10] = FinderPattern[i + (5 * c_left)]; barWeights[i + 31] = FinderPattern[(4 - i) + (5 * c_right)]; } EncodedData.Add(""); foreach (int val in barWeights) EncodedData[0] += val; return EncodedData[0]; } internal override float GetWidth(string code) { float width = 0; for (int x = 0; x < EncodedData[0].Length; x++) width += EncodedData[0][x] - '0'; return width * WideBarRatio; } /// internal override void DoLines(string data, IGraphics g, float zoom) { DrawLineBars(EncodedData[0], g, zoom, new RectangleF(0, 0, 0, barArea.Height), false); } } /// /// Generates the GS1 DataBar Stacked barcode. /// public class BarcodeGS1Stacked : BarcodeGS1Omnidirectional { internal override string GetPattern() { string data = base.GetPattern(); EncodedData = new List(); EncodedData.Add(data.Substring(0, 23) + "11"); EncodedData.Add("0000"); // left padding of separate line EncodedData.Add("11" + data.Substring(23, 23)); // convert line of strokes to black and white modules string[] bars = new string[2]; for(int i = 0; i < EncodedData[0].Length; i++) { if(i % 2 == 0) { for (int x = 0; x < EncodedData[0][i] - '0'; x++) bars[0] += "0"; for (int x = 0; x < EncodedData[2][i] - '0'; x++) bars[1] += "1"; } else { for (int x = 0; x < EncodedData[0][i] - '0'; x++) bars[0] += "1"; for (int x = 0; x < EncodedData[2][i] - '0'; x++) bars[1] += "0"; } } // Encode separate line (applying encoding rules from sections 5.3.2.1) for (int i = 4; i < bars[0].Length - 4; i++) { if (bars[0][i] == '1' && bars[1][i] == '1') EncodedData[1] += "0"; else if(bars[0][i] == '0' && bars[1][i] == '0') EncodedData[1] += "1"; else if(bars[0][i] != bars[1][i]) { EncodedData[1] += EncodedData[1][EncodedData[1].Length - 1] == '0' ? "1" : "0"; } } return ""; } /// internal override void DoLines(string data, IGraphics g, float zoom) { DrawLineBars(EncodedData[0], g, zoom, new RectangleF(0, 0, 0, barArea.Height * 5 / 13), false); DrawLineBars(EncodedData[1], g, zoom, new RectangleF(0, barArea.Height * 5 / 13, 0, barArea.Height * 1 / 13), false, true); DrawLineBars(EncodedData[2], g, zoom, new RectangleF(0, barArea.Height * 6 / 13, 0, barArea.Height * 7 / 13), true); } internal override float GetWidth(string code) { float width = 0; for (int x = 0; x < EncodedData[0].Length; x++) width += EncodedData[0][x] - '0'; return width * WideBarRatio; } } /// /// Generates the GS1 DataBar Stacked Omnidirectional barcode. /// public class BarcodeGS1StackedOmnidirectional : BarcodeGS1Omnidirectional { internal override string GetPattern() { string[] bars = new string[2]; bool nextBarBlack = true; bool nextBarWhite = true; string data = base.GetPattern(); EncodedData = new List(); EncodedData.Add(data.Substring(0, 23) + "11"); EncodedData.Add("0000"); // left padding of top separate line EncodedData.Add("0000010101010101010101010101010101010101010101"); // left padding of middle separate line EncodedData.Add("0000"); // left padding of bottom separate line EncodedData.Add("11" + data.Substring(23, 23)); // Encode separate lines (applying encoding rules from sections 5.3.2.2) for (int i = 0; i < EncodedData[0].Length; i++) { if (i % 2 == 0) { for (int x = 0; x < EncodedData[0][i] - '0'; x++) { if (i > 5 && i < 9) { if (nextBarBlack) { bars[0] += "1"; nextBarBlack = false; } else { bars[0] += "0"; nextBarBlack = true; } } else bars[0] += "1"; } for (int x = 0; x < EncodedData[4][i] - '0'; x++) { if (i > 15 && i < 19) { if (nextBarWhite) { bars[1] += "0"; nextBarWhite = false; } else { bars[1] += "1"; nextBarWhite = true; } } else bars[1] += "0"; } } else { for (int x = 0; x < EncodedData[0][i] - '0'; x++) { bars[0] += "0"; } for (int x = 0; x < EncodedData[4][i] - '0'; x++) { bars[1] += "1"; } } } EncodedData[1] += bars[0].Remove(0, 4).Remove(42, 4); EncodedData[3] += bars[1].Remove(0, 4).Remove(42, 4); return ""; } internal override float GetWidth(string code) { float width = 0; for (int x = 0; x < EncodedData[0].Length; x++) width += EncodedData[0][x] - '0'; return width * WideBarRatio; } /// internal override void DoLines(string data, IGraphics g, float zoom) { DrawLineBars(EncodedData[0], g, zoom, new RectangleF(0, 0, 0, barArea.Height * 33 / 69), false); DrawLineBars(EncodedData[1], g, zoom, new RectangleF(0, barArea.Height * 33 / 69 , 0, barArea.Height * 1 / 69), false, true); DrawLineBars(EncodedData[2], g, zoom, new RectangleF(0, barArea.Height * 34 / 69 , 0, barArea.Height * 1 / 69), false, true); DrawLineBars(EncodedData[3], g, zoom, new RectangleF(0, barArea.Height * 35 / 69 , 0, barArea.Height * 1 / 69), false, true); DrawLineBars(EncodedData[4], g, zoom, new RectangleF(0, barArea.Height * 36 / 69 , 0, barArea.Height * 33 / 69), true); } } /// /// Generates the GS1 DataBar Limited barcode. /// public class BarcodeGS1Limited : BarcodeGS1Base { /// /// Get value for encoding. /// /// Data /// protected long GetValue(string data) { long result; string prefix = ""; int startPrefix = data.IndexOf('('); int endPrefix = data.IndexOf(')'); if (startPrefix >= 0 && endPrefix > 0) { prefix = data.Substring(startPrefix, endPrefix + 1); data = data.Replace(prefix, ""); } if (data.Length > 13) data = data.Remove(13, 1); if (!long.TryParse(data, out result) || data.Length != 13 || result > 1999999999999 || result < 0) throw new FormatException(Res.Get("Messages,InvalidBarcode2")); if (prefix == "") prefix = "(01)"; this.text = prefix + CheckSumModulo10(data); return result; } int[] ChecksumWeight = { 1, 3, 9, 27, 81, 65, 17, 51, 64, 14, 42, 37, 22, 66, 20, 60, 2, 6, 18, 54, 73, 41, 34, 13, 39, 28, 84, 74 }; int[] FinderPattern = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1 }; int[] ModulesOdd = { 17, 13, 9, 15, 11, 19, 7 }; int[] ModulesEven = { 9, 13, 17, 11, 15, 7, 19 }; int[] WidthsOdd = { 6, 5, 3, 5, 4, 8, 1 }; int[] WidthsEven = { 3, 4, 6, 4, 5, 1, 8 }; int[] TEven = { 28, 728, 6454, 203, 2408, 1, 16632 }; internal override string GetPattern() { EncodedData = new List(); long value = GetValue(text); long left = value / 2013571; long right = value % 2013571; int leftGroup = 0; if (left > 183063) { leftGroup = 1; } if (left > 820063) { leftGroup = 2; } if (left > 1000775) { leftGroup = 3; } if (left > 1491020) { leftGroup = 4; } if (left > 1979844) { leftGroup = 5; } if (left > 1996938) { leftGroup = 6; } int rightGroup = 0; if (right > 183063) { rightGroup = 1; } if (right > 820063) { rightGroup = 2; } if (right > 1000775) { rightGroup = 3; } if (right > 1491020) { rightGroup = 4; } if (right > 1979844) { rightGroup = 5; } if (right > 1996938) { rightGroup = 6; } switch (leftGroup) { case 1: left -= 183064; break; case 2: left -= 820064; break; case 3: left -= 1000776; break; case 4: left -= 1491021; break; case 5: left -= 1979845; break; case 6: left -= 1996939; break; } switch (rightGroup) { case 1: right -= 183064; break; case 2: right -= 820064; break; case 3: right -= 1000776; break; case 4: right -= 1491021; break; case 5: right -= 1979845; break; case 6: right -= 1996939; break; } int leftOdd = (int)(left / TEven[leftGroup]); int leftEven = (int)(left % TEven[leftGroup]); int rightOdd = (int)(right / TEven[rightGroup]); int rightEven = (int)(right % TEven[rightGroup]); List widths; int[] leftWidths = new int[14]; int[] rightWidths = new int[14]; widths = GetGS1Widths(leftOdd, ModulesOdd[leftGroup], 7, WidthsOdd[leftGroup], 1); leftWidths[0] = widths[0]; leftWidths[2] = widths[1]; leftWidths[4] = widths[2]; leftWidths[6] = widths[3]; leftWidths[8] = widths[4]; leftWidths[10] = widths[5]; leftWidths[12] = widths[6]; widths = GetGS1Widths(leftEven, ModulesEven[leftGroup], 7, WidthsEven[leftGroup], 0); leftWidths[1] = widths[0]; leftWidths[3] = widths[1]; leftWidths[5] = widths[2]; leftWidths[7] = widths[3]; leftWidths[9] = widths[4]; leftWidths[11] = widths[5]; leftWidths[13] = widths[6]; widths = GetGS1Widths(rightOdd, ModulesOdd[rightGroup], 7, WidthsOdd[rightGroup], 1); rightWidths[0] = widths[0]; rightWidths[2] = widths[1]; rightWidths[4] = widths[2]; rightWidths[6] = widths[3]; rightWidths[8] = widths[4]; rightWidths[10] = widths[5]; rightWidths[12] = widths[6]; widths = GetGS1Widths(rightEven, ModulesEven[rightGroup], 7, WidthsEven[rightGroup], 0); rightWidths[1] = widths[0]; rightWidths[3] = widths[1]; rightWidths[5] = widths[2]; rightWidths[7] = widths[3]; rightWidths[9] = widths[4]; rightWidths[11] = widths[5]; rightWidths[13] = widths[6]; int checksum = 0; /* Calculate the checksum */ for (int i = 0; i < 14; i++) { checksum += ChecksumWeight[i] * leftWidths[i]; checksum += ChecksumWeight[i + 14] * rightWidths[i]; } checksum %= 89; int[] checkElements = new int[14]; for (int i = 0; i < 14; i++) { checkElements[i] = FinderPattern[i + (checksum * 14)]; } int[] totalWidths = new int[46]; totalWidths[0] = 1; totalWidths[1] = 1; totalWidths[44] = 1; totalWidths[45] = 1; for (int i = 0; i < 14; i++) { totalWidths[i + 2] = leftWidths[i]; totalWidths[i + 16] = checkElements[i]; totalWidths[i + 30] = rightWidths[i]; } EncodedData.Add(""); foreach (int val in totalWidths) EncodedData[0] += val; return EncodedData[0]; } /// internal override void DoLines(string data, IGraphics g, float zoom) { DrawLineBars(EncodedData[0], g, zoom, new RectangleF(0, 0, 0, barArea.Height), false); } internal override float GetWidth(string code) { float width = 0; for (int x = 0; x < EncodedData[0].Length; x++) width += EncodedData[0][x] - '0'; return width * WideBarRatio; } } }