public void Test_Renderer_EAN_UPC(BarcodeType type, MeasureBarcodeType heightToCutType, float heightToCutValue, int scaleMultiplier, bool hasQuiteZones, bool rotate90, string caseName)
        {
            MeasureBarcodeUnit heightToCut = new MeasureBarcodeUnit(heightToCutValue, heightToCutType);
            BarcodeRotation    rotation    = BarcodeRotation.Clockwise_0;

            if (rotate90)
            {
                rotation = BarcodeRotation.Clockwise_90;
            }
            switch (type)
            {
            case BarcodeType.EAN_13:
                int widthShould  = EANData.default_barcode_width_EAN_13 * scaleMultiplier;
                int heightShould = BarcodesUtils.GetBarcodeHeightInt(widthShould, type);
                heightShould = heightShould - (int)(heightShould * BarcodesUtils.GetPercentToCut(heightShould, heightToCut, scaleMultiplier) / 100);
                Bitmap bitmap = BarcodesRenderer.DrawBitmapEAN_UPC(
                    BarcodesTestData.encodedTestDataEAN_13,
                    BarcodesTestData.inputTestStringEAN_13,
                    type, heightToCut, true, scaleMultiplier, null, null, hasQuiteZones, rotation);
                if (!hasQuiteZones)
                {
                    widthShould = widthShould - (EANData.left_quite_zone_count_EAN_13 + EANData.right_quite_zone_count) * scaleMultiplier;
                }
                if (rotate90)
                {
                    bitmap.Width.Should().Be(heightShould);
                    bitmap.Height.Should().Be(widthShould);
                }
                else
                {
                    bitmap.Width.Should().Be(widthShould);
                    bitmap.Height.Should().Be(heightShould);
                }
                break;

            case BarcodeType.EAN_8:
                widthShould  = EANData.default_barcode_width_EAN_8 * scaleMultiplier;
                heightShould = BarcodesUtils.GetBarcodeHeightInt(widthShould, type);
                heightShould = heightShould - (int)(heightShould * BarcodesUtils.GetPercentToCut(heightShould, heightToCut, scaleMultiplier) / 100);
                bitmap       = BarcodesRenderer.DrawBitmapEAN_UPC(
                    BarcodesTestData.encodedTestDataEAN_8,
                    BarcodesTestData.inputTestStringEAN_8,
                    type, heightToCut, true, scaleMultiplier, null, null, hasQuiteZones, rotation);
                if (!hasQuiteZones)
                {
                    widthShould = widthShould - (EANData.left_quite_zone_count_EAN_8 + EANData.right_quite_zone_count) * scaleMultiplier;
                }
                if (rotate90)
                {
                    bitmap.Width.Should().Be(heightShould);
                    bitmap.Height.Should().Be(widthShould);
                }
                else
                {
                    bitmap.Width.Should().Be(widthShould);
                    bitmap.Height.Should().Be(heightShould);
                }
                break;

            case BarcodeType.UPC_A:
                widthShould  = EANData.default_barcode_width_EAN_13 * scaleMultiplier;
                heightShould = BarcodesUtils.GetBarcodeHeightInt(widthShould, type);
                heightShould = heightShould - (int)(heightShould * BarcodesUtils.GetPercentToCut(heightShould, heightToCut, scaleMultiplier) / 100);
                bitmap       = BarcodesRenderer.DrawBitmapEAN_UPC(
                    BarcodesTestData.encodedTestDataUPC_A,
                    BarcodesTestData.inputTestStringUPC_A,
                    type, heightToCut, true, scaleMultiplier, null, null, hasQuiteZones, rotation);
                if (!hasQuiteZones)
                {
                    widthShould = widthShould - (EANData.left_quite_zone_count_EAN_13 + EANData.right_quite_zone_count) * scaleMultiplier;
                }
                if (rotate90)
                {
                    bitmap.Width.Should().Be(heightShould);
                    bitmap.Height.Should().Be(widthShould);
                }
                else
                {
                    bitmap.Width.Should().Be(widthShould);
                    bitmap.Height.Should().Be(heightShould);
                }
                break;
            }

            Assert.True(true, caseName);
        }
예제 #2
0
        /// <summary>
        /// Draws a EAN/UPC barcode on bitmap from the encoded data depending on the barcode type and returns bitmap.
        /// </summary>
        /// <param name="encodedData">The encoded data.</param>
        /// <param name="barcodeType">The barcode type.</param>
        /// <param name="strokeColor">The color of barcode lines.</param>
        /// <param name="backColor">The background color.</param>
        /// <param name="showDataLabel">Defines whether to print the barcode data under the lines.</param>
        /// <param name="textDataString">The text to be printed under the barcode lines.</param>
        /// <param name="heightToCut">The height in pixels or in percent to be cut from the top of the barcode lines. Can be 0.</param>
        /// <param name="scaleMultiplier">The multiplier of the barcode width for better text rendering.</param>
        /// <param name="hasQuietZones">Defines whether the barcode has quiet zones.</param>
        /// <param name="barcodeRotation">Defines barcode rotation angle.</param>
        /// <returns>Bitmap</returns>
        internal static Bitmap DrawBitmapEAN_UPC(byte[] encodedData, string textDataString, BarcodeType barcodeType,
                                                 MeasureBarcodeUnit heightToCut, bool showDataLabel, int scaleMultiplier = 2, Color?strokeColor = null, Color?backColor = null,
                                                 bool hasQuietZones = true, BarcodeRotation barcodeRotation = BarcodeRotation.Clockwise_0)
        {
            // Bitmap accepts only integer values:
            int    barcodeWidth;
            int    barcodeHeight;
            int    strokeHeight;
            int    separatorHeight;
            int    leftQuiteZoneCount;
            int    leftCodePartCount;
            int    shiftFromTop   = EANData.shift_from_top * scaleMultiplier;
            Font   labelFont      = new Font(EANData.font_family_name, EANData.default_font_size * scaleMultiplier);
            Font   labelFontSmall = new Font(EANData.font_family_name, EANData.default_font_small_size * scaleMultiplier);
            string textDataLeft;
            string textDataRight;
            int    dotsPerInch      = EANData.dots_per_inch;
            int    halfBarItemWidth = scaleMultiplier / 2;

            switch (barcodeType)
            {
            case BarcodeType.EAN_13:
            case BarcodeType.UPC_A:
                barcodeWidth       = EANData.default_barcode_width_EAN_13 * scaleMultiplier;
                barcodeHeight      = BarcodesUtils.GetBarcodeHeightInt(EANData.default_barcode_width_EAN_13 * scaleMultiplier, barcodeType);
                strokeHeight       = BarcodesUtils.GetStrokeHeight(EANData.default_barcode_width_EAN_13 * scaleMultiplier, barcodeType);
                separatorHeight    = BarcodesUtils.GetSeparatorHeight(EANData.default_barcode_width_EAN_13 * scaleMultiplier, barcodeType);
                leftQuiteZoneCount = EANData.left_quite_zone_count_EAN_13;
                leftCodePartCount  = 42;
                textDataLeft       = textDataString.Substring(0, 6);
                textDataRight      = textDataString.Substring(6, 6);
                if (barcodeType == BarcodeType.UPC_A)
                {
                    textDataLeft  = textDataLeft.Substring(1, 5);
                    textDataRight = textDataRight.Substring(0, 5);
                }
                break;

            case BarcodeType.EAN_8:
                barcodeWidth       = EANData.default_barcode_width_EAN_8 * scaleMultiplier;
                barcodeHeight      = BarcodesUtils.GetBarcodeHeightInt(EANData.default_barcode_width_EAN_8 * scaleMultiplier, barcodeType);
                strokeHeight       = BarcodesUtils.GetStrokeHeight(EANData.default_barcode_width_EAN_8 * scaleMultiplier, barcodeType);
                separatorHeight    = BarcodesUtils.GetSeparatorHeight(EANData.default_barcode_width_EAN_8 * scaleMultiplier, barcodeType);
                leftQuiteZoneCount = EANData.left_quite_zone_count_EAN_8;
                leftCodePartCount  = 28;
                textDataLeft       = textDataString.Substring(0, 4);
                textDataRight      = textDataString.Substring(4, 4);
                break;

            default:
                throw new System.NotImplementedException("BarcodeType is not supported");
            }

            int leftSeparatorCount   = 3;
            int middleSeparatorCount = 5;
            int rightQuiteZoneCount  = EANData.right_quite_zone_count;

            if (!hasQuietZones)
            {
                barcodeWidth        = barcodeWidth - (leftQuiteZoneCount + rightQuiteZoneCount) * scaleMultiplier;
                leftQuiteZoneCount  = 0;
                rightQuiteZoneCount = 0;
            }

            // Calculate the percent the user wants to cut from the top depending on height:
            float percentToCut = BarcodesUtils.GetPercentToCut(barcodeHeight, heightToCut, scaleMultiplier);

            int cut = (int)(barcodeHeight * percentToCut / 100);

            strokeHeight    = Math.Max(strokeHeight - cut, 0);
            separatorHeight = Math.Max(separatorHeight - cut, 0);
            barcodeHeight   = barcodeHeight - cut;

            Bitmap bitmap;

            bitmap = new Bitmap(barcodeWidth, barcodeHeight);

            bitmap.SetResolution(dotsPerInch, dotsPerInch);

            using (var graphics = Graphics.FromImage(bitmap))
            {
                void DrawStrokeLine(int pos, bool isSeparator = false)
                {
                    graphics.DrawLine(new Pen(strokeColor ?? Color.Black, scaleMultiplier),
                                      new PointF(pos * scaleMultiplier + halfBarItemWidth, shiftFromTop),
                                      new PointF(pos * scaleMultiplier + halfBarItemWidth, shiftFromTop + (isSeparator ? separatorHeight : strokeHeight)));
                }

                void DrawSpaceLine(int pos, bool isSeparator = false)
                {
                    graphics.DrawLine(new Pen(backColor ?? Color.White, scaleMultiplier),
                                      new PointF(pos * scaleMultiplier + halfBarItemWidth, shiftFromTop),
                                      new PointF(pos * scaleMultiplier + halfBarItemWidth, shiftFromTop + (isSeparator ? separatorHeight : strokeHeight)));
                }

                // Paint the background:
                graphics.Clear(backColor ?? Color.White);

                int x = 0;

                // Left quite zone:
                while (x < leftQuiteZoneCount)
                {
                    DrawSpaceLine(x++);
                }

                // Left separator:
                DrawStrokeLine(x++, true);
                DrawSpaceLine(x++, true);
                DrawStrokeLine(x++, true);

                // Left part of the barcode:
                while (x - leftQuiteZoneCount - leftSeparatorCount < leftCodePartCount)
                {
                    // First digit of UPC must be longer than the others:
                    bool isFirstDigit = (x - leftQuiteZoneCount - leftSeparatorCount >= 0) && (x - leftQuiteZoneCount - leftSeparatorCount <= 6);
                    if (encodedData[x - leftQuiteZoneCount - leftSeparatorCount] == 1)
                    {
                        DrawStrokeLine(x, (barcodeType == BarcodeType.UPC_A) && isFirstDigit);
                    }
                    else
                    {
                        DrawSpaceLine(x, (barcodeType == BarcodeType.UPC_A) && isFirstDigit);
                    }
                    x++;
                }

                // Middle separator:
                DrawSpaceLine(x++, true);
                DrawStrokeLine(x++, true);
                DrawSpaceLine(x++, true);
                DrawStrokeLine(x++, true);
                DrawSpaceLine(x++, true);

                // Right part of the barcode:
                while (x - leftQuiteZoneCount - leftSeparatorCount - middleSeparatorCount < leftCodePartCount * 2)
                {
                    // Last digit of UPC must be longer than the others:
                    bool isLastDigit = (x - leftQuiteZoneCount - leftSeparatorCount - middleSeparatorCount >= 77) && (x - leftQuiteZoneCount - leftSeparatorCount - middleSeparatorCount <= 83);
                    if (encodedData[x - leftQuiteZoneCount - leftSeparatorCount - middleSeparatorCount] == 1)
                    {
                        DrawStrokeLine(x, (barcodeType == BarcodeType.UPC_A) && isLastDigit);
                    }
                    else
                    {
                        DrawSpaceLine(x, (barcodeType == BarcodeType.UPC_A) && isLastDigit);
                    }
                    x++;
                }

                // Right separator:
                DrawStrokeLine(x++, true);
                DrawSpaceLine(x++, true);
                DrawStrokeLine(x++, true);

                // Right quite zone:
                for (int i = 0; i < rightQuiteZoneCount; i++)
                {
                    DrawSpaceLine(x++);
                }

                if (showDataLabel)
                {
                    var digitsPath  = new GraphicsPath();
                    var digitsBrush = new SolidBrush(strokeColor ?? Color.Black);

                    int oneDigitShift = 0;
                    if (barcodeType == BarcodeType.UPC_A)
                    {
                        oneDigitShift = 7;
                    }

                    graphics.SmoothingMode = SmoothingMode.AntiAlias;

                    float textPosY = barcodeHeight - 1 - labelFont.Size;

                    digitsPath.AddString(textDataLeft, labelFont.FontFamily, (int)labelFont.Style, labelFont.Size,
                                         new RectangleF(
                                             (leftQuiteZoneCount + leftSeparatorCount + oneDigitShift + 3) * scaleMultiplier,
                                             textPosY,
                                             (leftCodePartCount + 7) * scaleMultiplier,
                                             labelFont.Height
                                             ),
                                         StringFormat.GenericTypographic);
                    digitsPath.AddString(textDataRight, labelFont.FontFamily, (int)labelFont.Style, labelFont.Size,
                                         new RectangleF(
                                             (leftQuiteZoneCount + leftSeparatorCount + 2 + leftCodePartCount + middleSeparatorCount) * scaleMultiplier,
                                             textPosY,
                                             (leftCodePartCount + 7) * scaleMultiplier,
                                             labelFont.Height
                                             ),
                                         StringFormat.GenericTypographic);

                    // Print the first digit for EAN-13:
                    if ((barcodeType == BarcodeType.EAN_13) && hasQuietZones)
                    {
                        digitsPath.AddString(textDataString.Substring(0, 1), labelFont.FontFamily, (int)labelFont.Style, labelFont.Size,
                                             new RectangleF(
                                                 1 * scaleMultiplier,
                                                 textPosY,
                                                 (leftCodePartCount + 7) * scaleMultiplier,
                                                 labelFont.Height
                                                 ),
                                             StringFormat.GenericTypographic);
                    }

                    // Print the first and the last digits for UPC-A:
                    if ((barcodeType == BarcodeType.UPC_A) && hasQuietZones)
                    {
                        digitsPath.AddString(textDataString.Substring(0, 1), labelFontSmall.FontFamily, (int)labelFontSmall.Style, labelFontSmall.Size,
                                             new RectangleF(
                                                 2 * scaleMultiplier,
                                                 (textPosY + labelFont.Size - labelFontSmall.Size),
                                                 (7) * scaleMultiplier,
                                                 labelFontSmall.Height
                                                 ),
                                             StringFormat.GenericTypographic);

                        digitsPath.AddString(textDataRight, labelFontSmall.FontFamily, (int)labelFontSmall.Style, labelFontSmall.Size,
                                             new RectangleF(
                                                 (leftQuiteZoneCount + leftSeparatorCount * 2 + 2 + leftCodePartCount * 2 + middleSeparatorCount) * scaleMultiplier,
                                                 (textPosY + labelFont.Size - labelFontSmall.Size),
                                                 (7) * scaleMultiplier,
                                                 labelFontSmall.Height
                                                 ),
                                             StringFormat.GenericTypographic);
                    }

                    graphics.FillPath(digitsBrush, digitsPath);
                }
            }

            switch (barcodeRotation)
            {
            case BarcodeRotation.Clockwise_90:
                bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
                break;

            case BarcodeRotation.Clockwise_180:
                bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                break;

            case BarcodeRotation.Clockwise_270:
                bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
                break;
            }

            return(bitmap);
        }