// **************************************************************
// IDAutomation DotCode Font Encoder 2020
// © Copyright, 2020 IDAutomation.com, Inc. All rights reserved.
// Portions of this program utilize IDAutomation USA Patent 7,637,436
// 
// Limitations of the Demo Version:
// The demo version of this product includes a fully
// functional 2D font and is designed only for the
// purpose of testing the font in various applications
// and point sizes. To generate dynamic symbols,
// a font encoder is required to format the data being
// encoded into the 2D symbol.
// Only static data can be provided for the encoders
// in the demo version, because providing a working
// encoder would reveal the complete source code,
// which is only available in the licensed version.
// To order, please visit:
// https://www.idautomation.com/
//*****************************************************************
//
// Please refer to the User Manual and Included Examples
// https://www.idautomation.com/barcode-components/dotnet-standard/
//
//*****************************************************************


using System;
using System.Text;

namespace IDAutomation.NetStandard.DotCode.FontEncoder
{

    /// <summary>
/// FontEncoder DotCode barcode class.
/// </summary>
    public class DotCode
    {

        private int[][] aMatrix;
        private int NCOL;
        private int NROW;
        private int iQZ;

        // '   Optional Parameter Defaults may be changed below
        // '   DataToEncode                 text to encode
        // '   ReturnType                   0 (font circles), 1 (font squares), 2 (Courier), 3 (Courier), 4 (Courier)
        // '   ProcessTilde = 1             If = 1 the Tilde will be processed | http://www.idautomation.com/barcode-faq/2d/dotcode/#Control_Characters
        // '   Mask = 0                     Default 0 (best mask, fast process), 1 (best mask, slow process), 2 (Mask 0), 3 (Mask 1), 4 (Mask 2), 5 (Mask 3)
        // '                                When = 1 the mask will be processed and symbols will take more time to generate
        // '   NewLineCharacter = vbCrLf

        /// <summary>
        /// Function, which creates a dotcode barcode, depending on the various input options chosen.
        /// </summary>
        /// <param name="DataToEncode">The data that Is encoded in the barcode.</param>
        /// <param name="ApplyTilde">Enables processing of tilde And parentheses characters for purposes of encoding ASCII functions And GS1 application identifiers.</param>
        /// <param name="EncodingMode">Various modes used to Data represented in the symbol may be encoded by one of these types.</param>
        /// <param name="Ratio">Represents the Columns (Width) to Rows (Height) Aspect Ratio.</param>
        /// <param name="Columns">Represents the columns sizes of the symbol.</param>
        /// <param name="Rows">Represents the rows sizes of the symbol.</param>
        /// <param name="Mask">Represents the various pattern for mask of the symbol.</param>
        /// <param name="QuietZone">Define the size of a blank zone around the code.</param>
        /// <param name="ModuleSize">Define the size of each module.</param>
        /// <returns>An array representation of barcode's image.</returns>
        public byte[] EncodeDotCode(string DataToEncode, bool ApplyTilde = true, EncodingModes EncodingMode = EncodingModes.Auto, int Ratio = 21, int Columns = 0, int Rows = 0, int Mask = 0, int QuietZone = 1, int ModuleSize = 1)
        {
            _encode(DataToEncode, ApplyTilde, EncodingMode, Ratio, Columns, Rows, Mask, QuietZone);

            byte[] Result = null;

            int k;
            int intPad = 0;
            int pixels;
            int bit;
            int bWidth;
            int x;
            int y;
            int ncols;
            int nrows;

            ModuleSize = ModuleSize * 2 + 1;
            ncols = (NCOL + 2 * iQZ) * ModuleSize;
            nrows = (NROW + 2 * iQZ) * ModuleSize;
            bWidth = (int)(Math.Floor(ncols / 8d) + (ncols % 8 > 0 ? 1 : 0));
            int intTemp = bWidth % 4;
            if (intTemp != 0)
            {
                intPad = 4 - intTemp;
            }

            Result = new byte[(64 + nrows * (bWidth + intPad))];
            Result[0] = 0x42;
            Result[1] = 0x4D;
            for (k = 0; k <= 7; k++)
                Result[2 + k] = 0;
            Result[10] = 0x3E;
            for (k = 0; k <= 2; k++)
                Result[11 + k] = 0;
            Result[14] = 0x28;
            for (k = 0; k <= 2; k++)
                Result[15 + k] = 0;

            // ' width
            Result[18] = (byte)Math.Floor((decimal)(ncols % 256));
            Result[19] = (byte)Math.Floor(ncols / 256d);
            Result[20] = 0;
            Result[21] = 0;

            // ' height
            Result[22] = (byte)Math.Floor((decimal)(nrows % 256));
            Result[23] = (byte)Math.Floor(nrows / 256d);
            Result[24] = 0;
            Result[25] = 0;
            Result[26] = 1;
            Result[27] = 0;
            Result[28] = 1;
            Result[29] = 0;
            for (k = 0; k <= 7; k++)
                Result[30 + k] = 0;
            Result[38] = 0x25;
            Result[39] = 0xE;
            Result[40] = 0;
            Result[41] = 0;
            Result[42] = 0x25;
            Result[43] = 0xE;
            Result[44] = 0;
            Result[45] = 0;
            for (k = 0; k <= 7; k++)
                Result[46 + k] = 0;
            for (k = 0; k <= 2; k++)
                Result[54 + k] = 0xFF;
            for (k = 0; k <= 4; k++)
                Result[57 + k] = 0;
            int pos = 62;
            bool bFlag;
            int cx;
            int cy;
            for (y = nrows - 1; y >= 0; y -= 1)
            {
                pixels = 0;
                bit = 8;
                int loopTo = ncols - 1;
                for (x = 0; x <= loopTo; x++)
                {
                    bFlag = aMatrix[(int)(y / (double)ModuleSize)][ (int)(x / (double)ModuleSize)] != 0;
                    if (bFlag)
                    {
                        cx = (int)(x / ModuleSize) * ModuleSize + (int)(ModuleSize / 2d);
                        cy = (int)(y / ModuleSize) * ModuleSize + (int)(ModuleSize / 2d);

                        if (ModuleSize == 3)
                        {
                            bFlag = (cx == x | cy == y);
                        }
                        else
                        {
                            bFlag = bFlag & (Math.Pow(y - cy, 2d) + Math.Pow(x - cx, 2d) <= Math.Pow(ModuleSize / 2d, 2d));
                        }
                    }

                    if (bFlag)
                    {
                        bit = bit - 1;
                        pixels = pixels + (int)Math.Pow(2, bit);
                        if (bit == 0)
                        {
                            Result[pos] = (byte)pixels;
                            pos += 1;
                            bit = 8;
                            pixels = 0;
                        }

                    }
                    else
                    {
                        bit = bit - 1;
                        if (bit == 0)
                        {
                            Result[pos] = (byte)pixels;
                            pos += 1;
                            bit = 8;
                            pixels = 0;
                        }
                    }
                }

                if (bit != 8)
                {
                    Result[pos] = (byte)pixels;
                    pos += 1;
                }

                pos = pos + intPad;
            }

            return Result;
        }


        /// <summary>
        /// Function, which creates a dotcode barcode, depending on the various input options chosen.
        /// </summary>
        /// <param name="DataToEncode">The data that Is encoded in the barcode.</param>
        /// <param name="ApplyTilde">Enables processing of tilde And parentheses characters for purposes of encoding ASCII functions And GS1 application identifiers.</param>
        /// <param name="EncodingMode">Various modes used to Data represented in the symbol may be encoded by one of these types.</param>
        /// <param name="Ratio">Represents the Columns (Width) to Rows (Height) Aspect Ratio.</param>
        /// <param name="Columns">Represents the columns sizes of the symbol.</param>
        /// <param name="Rows">Represents the rows sizes of the symbol.</param>
        /// <param name="Mask">Represents the various pattern for mask of the symbol.</param>
        /// <param name="VectorType">Define the type of vector image for output.</param>
        /// <param name="NewLine">String indicating EOL character. Defaults to the operating system EOL character if left NULL.</param>
        /// <param name="QuietZone">Define the size of a blank zone around the code.</param>
        /// <param name="ModuleSize">Define the size of each module.</param>
        /// <returns>A string representation of vector dotcode's image.</returns>

        public string EncodeDotCode(string DataToEncode, bool ApplyTilde = true, EncodingModes EncodingMode = EncodingModes.Auto, int Ratio = 21, int Columns = 0, int Rows = 0, int Mask = 0, VectorTypes VectorType = VectorTypes.VecEPS, string NewLine = "", int QuietZone = 1, int ModuleSize = 1)
        {
            _encode(DataToEncode, ApplyTilde, EncodingMode, Ratio, Columns, Rows, Mask, QuietZone);

            // ' allows user to set an end-of-line (EOL) string
            if (string.IsNullOrEmpty(NewLine))
            {
                NewLine = Environment.NewLine; // ' Default
            }

            StringBuilder strOut = new StringBuilder("");
            string tempW;
            string tempH;
            int x;
            int y;
            int ncols;
            int nrows;
            ncols = NCOL + 2 * iQZ;
            nrows = NROW + 2 * iQZ;
            ModuleSize = ModuleSize * 4;
            tempW = (ncols * ModuleSize).ToString();
            tempH = (nrows * ModuleSize).ToString();
            if (VectorType == VectorTypes.VecSVG)
            {
                strOut.Append("<?xml version='1.0' standalone='no'?>" + NewLine);
                strOut.Append("<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>" + NewLine);
                strOut.Append("<svg width='" + tempW + "' height='" + tempH + "' version='1.1' xmlns='http://www.w3.org/2000/svg'>" + NewLine);
                strOut.Append("  <g id='dotcode'>" + NewLine);
                strOut.Append("    <g id='background' fill='#ffffff' stroke='#ffffff'>" + NewLine);
                strOut.Append("      <rect x='0' y='0' width='" + tempW + "' height='" + tempH + "' />" + NewLine);
                strOut.Append("    </g>" + NewLine);
                strOut.Append("    <g id='pattern' fill='#000000' stroke='#000000'>" + NewLine);
                int loopTo = nrows - 1;
                for (y = 0; y <= loopTo; y++)
                {
                    int loopTo1 = ncols - 1;
                    for (x = 0; x <= loopTo1; x++)
                    {
                        if (aMatrix[y][x] != 0)
                        {
                            strOut.Append("    <g id='R" + y.ToString() + "C" + x.ToString() + "' >" + NewLine);
                            strOut.Append( ("      <circle cx='" + ((x + 0.5d) * ModuleSize).ToString() + "' cy='" + ((y + 0.5d) * ModuleSize).ToString() + "' r='" + (0.98d * ModuleSize / 2d).ToString() + "' />").Replace(",", ".") + NewLine);
                            strOut.Append("    </g>" + NewLine);
                        }
                    }
                }

                strOut.Append("    </g>" + NewLine);
                strOut.Append("  </g>" + NewLine);
                strOut.Append("</svg>" + NewLine);
            }
            else if (VectorType == VectorTypes.VecEPS)
            {
                strOut.Append("%!PS-Adobe-3.0 EPSF-3.0" + NewLine);
                strOut.Append("%%Creator: IDAutomation.com" + NewLine);
                strOut.Append("%%Title: dotcode" + NewLine);
                strOut.Append("%%CreationDate: " + DateTime.Now.ToString("ddd mmm d hh:mm:ss yyyy") + NewLine);
                strOut.Append("%%BoundingBox: 0 0 " + tempW + " " + tempH + NewLine);
                strOut.Append("%%DocumentData: Clean7Bit" + NewLine);
                strOut.Append("%%EndComments" + NewLine);
                strOut.Append("%%BeginProlog" + NewLine);
                strOut.Append("/bd { bind def } bind def" + NewLine);
                strOut.Append("/incompound false def" + NewLine);
                strOut.Append("/m { moveto } bd" + NewLine);
                strOut.Append("/l { lineto } bd" + NewLine);
                strOut.Append("/*U { /incompound false def f} bd" + NewLine);
                strOut.Append("/k { setcmykcolor } bd" + NewLine);
                strOut.Append("/c { curveto } bd" + NewLine);
                strOut.Append("/F { incompound not {fill} if } bd" + NewLine);
                strOut.Append("/f { closepath F } bd" + NewLine);
                strOut.Append("/S { stroke } bd" + NewLine);
                strOut.Append("/*u { /incompound true def } bd" + NewLine);
                strOut.Append("/K { k } bd" + NewLine);
                strOut.Append("%%EndProlog" + NewLine);
                strOut.Append("%%BeginSetup" + NewLine);
                strOut.Append("%%EndSetup" + NewLine);
                strOut.Append("0.000 0.000 0.000 0.000 k" + NewLine);
                strOut.Append("0 0 m" + NewLine);
                strOut.Append("0 0 l" + NewLine);
                strOut.Append(tempW + " 0 l" + NewLine);
                strOut.Append(tempW + " " + tempH + " l" + NewLine);
                strOut.Append("0 " + tempH + " l" + NewLine);
                strOut.Append("f" + NewLine);
                strOut.Append("*U" + NewLine);

                float sngLx;
                float sngLy;
                sngLx = (float)(4d / 3d * (Math.Sqrt(2d) - 1d) * (ModuleSize / 2d));
                sngLy = (float)(4d / 3d * (Math.Sqrt(2d) - 1d) * (ModuleSize / 2d));
                strOut.Append("0.000 0.000 0.000 1.000 k" + NewLine);
                int loopTo2 = nrows - 1;
                for (y = 0; y <= loopTo2; y++)
                {
                    int loopTo3 = ncols - 1;
                    for (x = 0; x <= loopTo3; x++)
                    {
                        if (aMatrix[y][x] != 0)
                        {
                            strOut.Append((((x + 1) * ModuleSize).ToString() + " " + ((nrows - y - 0.5d) * ModuleSize).ToString() + " m").Replace(",", ".") + NewLine );
                            strOut.Append((((x + 1) * ModuleSize).ToString() + " " + (nrows * ModuleSize - ((y + 0.5d) * ModuleSize - sngLy)).ToString() + " " + ((x + 0.5d) * ModuleSize + sngLx).ToString() + " " + ((nrows - y) * ModuleSize).ToString() + " " + ((x + 0.5d) * ModuleSize).ToString() + " " + ((nrows - y) * ModuleSize).ToString() + " c").Replace(",", ".") + NewLine);
                            strOut.Append((((x + 0.5d) * ModuleSize - sngLx).ToString() + " " + ((nrows - y) * ModuleSize).ToString() + " " + (x * ModuleSize).ToString() + " " + (nrows * ModuleSize - ((y + 0.5d) * ModuleSize - sngLy)).ToString() + " " + (x * ModuleSize).ToString() + " " + ((nrows - y - 0.5d) * ModuleSize).ToString() + " c").Replace(",", ".") + NewLine);
                            strOut.Append(((x * ModuleSize).ToString() + " " + (nrows * ModuleSize - ((y + 0.5d) * ModuleSize + sngLy)).ToString() + " " + ((x + 0.5d) * ModuleSize - sngLx).ToString() + " " + ((nrows - y - 1) * ModuleSize).ToString() + " " + ((x + 0.5d) * ModuleSize).ToString() + " " + ((nrows - y - 1) * ModuleSize).ToString() + " c").Replace(",", ".") + NewLine);
                            strOut.Append((((x + 0.5d) * ModuleSize + sngLx).ToString() + " " + ((nrows - y - 1) * ModuleSize).ToString() + " " + ((x + 1) * ModuleSize).ToString() + " " + (nrows * ModuleSize - ((y + 0.5d) * ModuleSize + sngLy)).ToString() + " " + ((x + 1) * ModuleSize).ToString() + " " + ((nrows - y - 0.5d) * ModuleSize).ToString() + " c").Replace(",", ".") + NewLine);
                            strOut.Append("f" + NewLine);
                        }
                    }
                }

                strOut.Append("*U" + NewLine);
                strOut.Append("%%Trailer" + NewLine);
                strOut.Append("%%EOF" + NewLine);
            }
            else if (VectorType == VectorTypes.VecHTML)
            {
                strOut.Append("<meta http-equiv='X-UA-Compatible' content='IE=10' />");
                strOut.Append("<div style='font-size:0;background-color:#ffffff;position:relative;width:" + tempW + "px;height:" + tempH + "px;'>" + NewLine);
                int loopTo4 = nrows - 1;
                for (y = 0; y <= loopTo4; y++)
                {
                    int loopTo5 = ncols - 1;
                    for (x = 0; x <= loopTo5; x++)
                    {
                        if (aMatrix[y][x] != 0)
                        {
                            strOut.Append("<div style='-webkit-border-radius:50%; -moz-border-radius:50%; border-radius:50%; background:#000000;width:" + ModuleSize.ToString() + "px;height:" + ModuleSize.ToString() + "px;position:absolute;left:" + (x * ModuleSize).ToString() + "px;top:" + (y * ModuleSize).ToString() + "px;'>&nbsp</div>" + NewLine);
                        }
                    }
                }

                strOut.Append("</div>" + NewLine);
            }

            return strOut.ToString();
        }


        /// <summary>
        /// Function, which creates a dotcode barcode, depending on the various input options chosen.
        /// </summary>
        /// <param name="DataToEncode">The data that Is encoded in the barcode.</param>
        /// <param name="ReturnType">Represents the type of output text 0 (font circles), 1 (font squares), 2 (Courier), 3 (Courier), 4 (Courier)</param>
        /// <param name="ApplyTilde">Enables processing of tilde And parentheses characters for purposes of encoding ASCII functions And GS1 application identifiers.</param>
        /// <param name="EncodingMode">Various modes used to Data represented in the symbol may be encoded by one of these types.</param>
        /// <param name="Ratio">Represents the Columns (Width) to Rows (Height) Aspect Ratio.</param>
        /// <param name="Columns">Represents the columns sizes of the symbol.</param>
        /// <param name="Rows">Represents the rows sizes of the symbol.</param>
        /// <param name="NewLine">String indicating EOL character. Defaults to the operating system EOL character if left NULL.</param>
        /// <param name="Mask">Represents the various pattern for mask of the symbol.</param>
        /// <param name="QuietZone">Define the size of a blank zone around the code.</param>
        /// <returns>Encoded text for use with the 2D barcode font.</returns>
        public string EncodeDotCode(string DataToEncode, int ReturnType = 0, bool ApplyTilde = true, EncodingModes EncodingMode = EncodingModes.Auto, int Ratio = 21, int Columns = 0, int Rows = 0, string NewLine = "", int Mask = 0, int QuietZone = 1)
        {
            string EncodeDotCodeRet = default;

            // DataToEncode must have a value; otherwise null is returned

            EncodeDotCodeRet = "";
            try
            {
                if (DataToEncode.Length > 0 & ((int)EncodingMode >= -1 | (int)EncodingMode <= 3))
                {
                    _encode(DataToEncode, ApplyTilde, EncodingMode, Ratio, Columns, Rows, Mask, QuietZone);

                    // ' allows user to set an end-of-line (EOL) string
                    if (string.IsNullOrEmpty(NewLine))
                    {
                        NewLine = Environment.NewLine; // ' Default
                    }

                    EncodeDotCodeRet = Matrix2Font(ReturnType, NewLine);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return EncodeDotCodeRet;
        }

        private void _encode(string DataToEncode, bool ProcessTilde = true , EncodingModes EncodingMode = EncodingModes.Auto, int Ratio = 21, int Columns = 0, int Rows = 0, int Mask = 0, int QuietZone = 1)
        {

            iQZ = 1;

            NROW = 18;
            NCOL = 35;
            aMatrix = new int[20][];
            aMatrix[0] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            aMatrix[1] = new int[] { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
            aMatrix[2] = new int[] { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0 };
            aMatrix[3] = new int[] { 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0 };
            aMatrix[4] = new int[] { 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
            aMatrix[5] = new int[] { 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0};
            aMatrix[6] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0};
            aMatrix[7] = new int[] { 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0};
            aMatrix[8] = new int[] { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0};
            aMatrix[9] = new int[] { 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0};
            aMatrix[10] = new int[] { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0};
            aMatrix[11] = new int[] { 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0};
            aMatrix[12] = new int[] { 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0};
            aMatrix[13] = new int[] { 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0};
            aMatrix[14] = new int[] { 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            aMatrix[15] = new int[] { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0};
            aMatrix[16] = new int[] { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0};
            aMatrix[17] = new int[] { 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0};
            aMatrix[18] = new int[] { 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0};
            aMatrix[19] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        }


        private string Matrix2Font(int ReturnType, string NewLineCharacter)
        {
            string Matrix2FontRet = default;
            int x;
            int y;
            string result;
            string[] FontSet = new string[5];
            FontSet[0] = "abcdefghijklmnop";
            FontSet[1] = "ABCDEFGHIJKLMNOP";
            FontSet[2] = " " + "●";
            FontSet[3] = " " + "♦"; // ChrW(9670)
            FontSet[4] = "∙" + "●";
            result = "";
            if (ReturnType >= 0 & ReturnType <= 1)
            {
                int loopTo = NROW + 2 * iQZ - 1;
                for (y = 0; y <= loopTo; y += 4)
                {
                    int loopTo1 = NCOL + 2 * iQZ - 1;
                    for (x = 0; x <= loopTo1; x++)
                    {
                        if (aMatrix[y][ x] == 0)
                        {
                            if (aMatrix[y + 1][x] == 0)
                            {
                                if (aMatrix[y + 2][x] == 0)
                                {
                                    if (aMatrix[y + 3][x] == 0)
                                    {
                                        result = result + (char)FontSet[ReturnType][15];
                                    }
                                    else
                                    {
                                        result = result + (char)FontSet[ReturnType][14];
                                    }
                                }
                                else if (aMatrix[y + 3][x] == 0)
                                {
                                    result = result + (char)FontSet[ReturnType][13];
                                }
                                else
                                {
                                    result = result + (char)FontSet[ReturnType][12];
                                }
                            }
                            else if (aMatrix[y + 2][x] == 0)
                            {
                                if (aMatrix[y + 3][x] == 0)
                                {
                                    result = result + (char)FontSet[ReturnType][11];
                                }
                                else
                                {
                                    result = result + (char)FontSet[ReturnType][10];
                                }
                            }
                            else if (aMatrix[y + 3][x] == 0)
                            {
                                result = result + (char)FontSet[ReturnType][9];
                            }
                            else
                            {
                                result = result + (char)FontSet[ReturnType][8];
                            }
                        }
                        else if (aMatrix[y + 1][x] == 0)
                        {
                            if (aMatrix[y + 2][x] == 0)
                            {
                                if (aMatrix[y + 3][x] == 0)
                                {
                                    result = result + (char)FontSet[ReturnType][7];
                                }
                                else
                                {
                                    result = result + (char)FontSet[ReturnType][6];
                                }
                            }
                            else if (aMatrix[y + 3][x] == 0)
                            {
                                result = result + (char)FontSet[ReturnType][5];
                            }
                            else
                            {
                                result = result + (char)FontSet[ReturnType][4];
                            }
                        }
                        else if (aMatrix[y + 2][x] == 0)
                        {
                            if (aMatrix[y + 3][x] == 0)
                            {
                                result = result + (char)FontSet[ReturnType][3];
                            }
                            else
                            {
                                result = result + (char)FontSet[ReturnType][2];
                            }
                        }
                        else if (aMatrix[y + 3][x] == 0)
                        {
                            result = result + (char)FontSet[ReturnType][1];
                        }
                        else
                        {
                            result = result + (char)FontSet[ReturnType][0];
                        }
                    }

                    result = result + NewLineCharacter;
                }
            }
            else if (ReturnType > 1 & ReturnType <= 4)
            {
                int loopTo2 = NROW + 2 * iQZ - 1;
                for (y = 0; y <= loopTo2; y++)
                {
                    int loopTo3 = NCOL + 2 * iQZ - 1;
                    for (x = 0; x <= loopTo3; x++)
                    {
                        if (aMatrix[y][x] == 0)
                        {
                            result = result + (char)FontSet[ReturnType][0];
                        }
                        else
                        {
                            result = result + (char)FontSet[ReturnType][1];
                        }

                        // ' remove extraspace on QuietZone
                        if (x >= iQZ & x < NCOL + iQZ - 1)
                            result = result + (char)FontSet[ReturnType][0];
                    }

                    result = result + NewLineCharacter;
                }
            }

            Matrix2FontRet = result;
            return Matrix2FontRet;
        }

    }


    /// <summary>
/// Various modes used to Data represented in the symbol may be encoded by one of these types.
/// </summary>
    public enum EncodingModes
    {
        /// <summary>
    /// In this mode data Is encoded with SetCodeC
    /// </summary>
        Auto,

        /// <summary>
    /// In this mode data Is encoded with SetCodeA
    /// </summary>
        CodeSetA,

        /// <summary>
    /// In this mode data Is encoded with SetCodeB
    /// </summary>
        CodeSetB,


        /// <summary>
    /// In this mode data Is encoded with SetCodeC
    /// </summary>
        CodeSetC,

        /// <summary>
    /// In this mode data Is encoded with Binary
    /// </summary>
        Binary
    }


    /// <summary>
/// Various types of vector image output.
/// </summary>
    public enum VectorTypes
    {

        /// <summary>
    /// Returns a string with the SVG representation.
    /// </summary>
        VecSVG,

        /// <summary>
    /// Return a string with the EPS representation.
    /// </summary>
        VecEPS,

        /// <summary>
    /// Return a string with the HTML representation.
    /// </summary>
        VecHTML
    }
}