/// <summary>
        /// Draws barcode referenced points.
        /// </summary>
        /// <param name="canvas">The canvas.</param>
        /// <param name="barcodeInfo">The barcode.</param>
        /// <param name="paint">The paint information.</param>
        private void DrawBarcodeReferencePoints(Canvas canvas, IBarcodeInfo barcodeInfo, Paint paint)
        {
            BarcodeInfo2D barcodeInfo2D = barcodeInfo as BarcodeInfo2D;

            // if barcode is 2D barcode
            if (barcodeInfo2D != null)
            {
                float cellSize = (float)(barcodeInfo2D.CellWidth + barcodeInfo2D.CellHeight) / 2;
                if (cellSize > 15)
                {
                    cellSize = 15;
                }
                foreach (System.Drawing.PointF point in barcodeInfo2D.GetReferencePoints())
                {
                    canvas.DrawCircle(point.X, point.Y, cellSize / 2, paint);
                }
            }
        }
        /// <summary>
        /// Draws the barcode information.
        /// </summary>
        /// <param name="canvas">A canvas.</param>
        /// <param name="paint">A paint information.</param>
        /// <param name="barcodeInfo">A barcode.</param>
        /// <param name="scale">A scale value.</param>
        private void DrawBarcodeInfo(Canvas canvas, Paint paint, IBarcodeInfo barcodeInfo, float scale)
        {
            int alpha;
            // get barcode region
            Region barcodeRegion = barcodeInfo.Region;

            if (barcodeRegion == null)
            {
                return;
            }

            // determines whether barcode region should be filled
            bool fill;

            // if confidence of barcode recognition is "-1"
            if (barcodeInfo.Confidence == -1)
            {
                alpha       = 48;
                paint.Color = Color.LimeGreen;
                fill        = true;
            }
            // if confidence of barcode recognition is no less than "95"
            else if (barcodeInfo.Confidence >= 95)
            {
                alpha       = 64;
                paint.Color = Color.LimeGreen;
                fill        = true;
            }
            // if confidence of barcode recognition between 0 and 95
            else
            {
                paint.Color = Color.Red;
                BarcodeInfo2D barcodeInfo2D = barcodeInfo as BarcodeInfo2D;
                if (barcodeInfo2D != null && barcodeInfo2D.GetReferencePoints().Length > 0)
                {
                    alpha = 64;
                    fill  = false;
                }
                else
                {
                    alpha = 32;
                    fill  = true;
                }
            }
            // if barcode region should be filled
            if (fill)
            {
                paint.Alpha = alpha;
                // fill barcode region
                FillRegion(canvas, barcodeInfo.Region, paint);
            }
            paint.Alpha = alpha * 3;
            // if confidence of barcode recognition is no less than "95"
            if (barcodeInfo.Confidence >= 95)
            {
                paint.Color = Color.Orange;
            }
            // draw barcode reference points
            DrawBarcodeReferencePoints(canvas, barcodeInfo, paint);

            // if need draw barcode type
            if (barcodeInfo.BarcodeInfoClass == BarcodeInfoClass.Barcode2D || barcodeInfo.Confidence == -1 || barcodeInfo.Confidence >= 95)
            {
                // get barcode type name
                string text = Utils.GetBarcodeTypeString(barcodeInfo);

                // draw barcode type name
                DrawText(canvas, barcodeInfo.Region.Rectangle, text, _textSizeInPixels / scale, paint.Color, 255, true);
            }
        }
        /// <summary>
        /// Returns a string with extended barcode info.
        /// </summary>
        /// <param name="barcodeInfo">A barcode info.</param>
        /// <param name="textEncodingName">A text encoding name.</param>
        /// <returns>
        /// A string with extended barcode info.
        /// </returns>
        internal string GetExtendedBarcodeInfoString(IBarcodeInfo barcodeInfo, string textEncodingName)
        {
            // if barcode info is empty
            if (barcodeInfo == null)
            {
                return(string.Empty);
            }

            IBarcodeInfo info;

            if (barcodeInfo is BarcodeSubsetInfo)
            {
                info = ((BarcodeSubsetInfo)barcodeInfo).BaseBarcodeInfo;
            }
            else
            {
                info = barcodeInfo;
            }

            StringBuilder extendedInfo = new StringBuilder();

            // append barcode value
            try
            {
                extendedInfo.AppendLine(Utils.GetEncodedBarcodeValue(barcodeInfo, textEncodingName));
            }
            catch (NotSupportedException)
            {
                extendedInfo.AppendLine(Utils.GetEncodedBarcodeValue(barcodeInfo, "-1"));
            }
            extendedInfo.AppendLine();
            extendedInfo.AppendLine(Resources.GetString(Resource.String.metadata_message));
            extendedInfo.AppendLine();

            // if barcode is 2D barcode
            if (info is BarcodeInfo2D)
            {
                // get 2D barcode info
                BarcodeInfo2D info2D = (BarcodeInfo2D)info;
                // get matrix size
                extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.matrix_size_message), info2D.MatrixWidth, info2D.MatrixHeight));
                // get cell size
                extendedInfo.AppendLine(string.Format(CultureInfo.InvariantCulture, Resources.GetString(Resource.String.cell_size_message),
                                                      info2D.CellWidth, info2D.CellHeight));
                if (info2D.IsMirrored)
                {
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.mirrored_message), info2D.IsMirrored));
                }
            }
            // if barcode is 1D barcode
            if (info is BarcodeInfo1D)
            {
                // get 1D barcode info
                BarcodeInfo1D info1D = (BarcodeInfo1D)info;
                // get narrow bar count
                extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.narrow_bar_count_message), info1D.NarrowBarCount));
                // get narrow bar size
                extendedInfo.AppendLine(string.Format(CultureInfo.InvariantCulture, Resources.GetString(Resource.String.narrow_bar_size_message), info1D.NarrowBarSize));
            }

            if (info.SymbolComponents != null)
            {
                extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.symbol_component_count_message), info.SymbolComponents.Length));
            }

            if (info is StructuredAppendBarcodeInfo)
            {
                extendedInfo.AppendLine(Resources.GetString(Resource.String.reconstructed_message));
            }
            else
            {
                switch (info.BarcodeType)
                {
                // if barcode is PDF417
                case BarcodeType.PDF417:
                case BarcodeType.PDF417Compact:
                    // get PDF417 barcode info
                    PDF417Info pdf417Info = (PDF417Info)info;
                    // get rows count
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.rows_count_message), pdf417Info.RowsCount));
                    // get error correction level
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.error_correction_level_message),
                                                          Utils.PDF417ErrorCorrectionLevelToString(pdf417Info.ErrorCorrectionLevel)));
                    break;

                // if barcode is MicroPDF417
                case BarcodeType.MicroPDF417:
                    // get MicroPDF417 barcode info
                    MicroPDF417Info microPdf417Info = (MicroPDF417Info)info;
                    // get symbol type
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.symbol_type_message),
                                                          Utils.MicroPDF417SymbolTypeToString(microPdf417Info.SymbolType)));
                    break;

                // if barcode if DataMatrix
                case BarcodeType.DataMatrix:
                    // get DataMatrix barcode info
                    DataMatrixInfo dataMatrixInfo = (DataMatrixInfo)info;
                    // get symbol type
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.symbol_type_message),
                                                          Utils.DataMatrixSymbolTypeToString(dataMatrixInfo.Symbol.SymbolType)));
                    break;

                // if barcode is QR
                case BarcodeType.MicroQR:
                case BarcodeType.QR:
                    // get QR barcode info
                    QRInfo qrInfo = (QRInfo)info;
                    // get symbol version
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.symbol_version_message),
                                                          Utils.QRSymbolVersionToString(qrInfo.Symbol.Version)));
                    // get error correction level
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.error_correction_level_message),
                                                          Utils.QRErrorCorrectionLevelToString(qrInfo.ErrorCorrectionLevel)));
                    break;

                // if barcode is Aztec
                case BarcodeType.Aztec:
                    // get Aztec barcode info
                    AztecInfo aztecInfo = (AztecInfo)info;
                    // get symbol type
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.symbol_type_message),
                                                          Utils.AztecSymbolTypeToString(aztecInfo.Symbol.SymbolType)));
                    // get data layers
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.data_layers_message), aztecInfo.Symbol.DataLayers));
                    // get error correction data
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.error_correction_data_message),
                                                          aztecInfo.Symbol.ErrorCorrectionData.ToString("F3")));
                    break;

                // if barcode is HanXin
                case BarcodeType.HanXinCode:
                    // get HanXin barcode info
                    HanXinCodeInfo hanXinInfo = (HanXinCodeInfo)info;
                    // get symbol version
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.symbol_version_message),
                                                          Utils.HanXinCodeSymbolVersionToString(hanXinInfo.Symbol.Version)));
                    // get error correction level
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.error_correction_level_message),
                                                          Utils.HanXinCodeErrorCorrectionLevelToString(hanXinInfo.Symbol.ErrorCorrectionLevel)));
                    break;

                // if barcode is MaxiCode
                case BarcodeType.MaxiCode:
                    // get MaxiCode barcode info
                    MaxiCodeInfo maxiCodeInfo = (MaxiCodeInfo)info;
                    // get encoding mode
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.encoding_mode_message),
                                                          Utils.MaxiCodeEncodingModeToString(maxiCodeInfo.EncodingMode)));
                    break;

                // if barcode is RSS14
                case BarcodeType.RSS14:
                case BarcodeType.RSS14Stacked:
                case BarcodeType.RSSExpanded:
                case BarcodeType.RSSExpandedStacked:
                case BarcodeType.RSSLimited:
                    // get RSS barcode info
                    RSSInfo rssInfo = (RSSInfo)info;
                    // get segments count
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.segments_count_message), rssInfo.SegmentsCount));
                    // get rows count
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.rows_count_message), rssInfo.RowsCount));
                    // get segments in row
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.segments_in_row_message), rssInfo.SegmentsInRow));
                    // get linkage flag
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.linkage_flag_message), rssInfo.LinkageFlag));
                    break;

                // if barcode is UPCE
                case BarcodeType.UPCE:
                    // get UPCE barcode info
                    UPCEANInfo upcEANInfo = (UPCEANInfo)info;
                    // get UPCE value
                    extendedInfo.AppendLine(string.Format(Resources.GetString(Resource.String.upce_value_message), upcEANInfo.UPCEValue));
                    break;
                }
            }

            extendedInfo.AppendLine(string.Format(CultureInfo.InvariantCulture, Resources.GetString(Resource.String.recognition_quality_message), info.ReadingQuality));

            return(extendedInfo.ToString());
        }