3
\$\begingroup\$

Can I improve this code and make it more beautiful? For example, I am using a switch statement and for each page but I only add edits to page 1 and page 2?

byte[] b = null;
MemoryStream stream = new MemoryStream(buffer);
string _Number = "4.2021";
string _disclaimer = "Text";

using (MemoryStream returnMemoryStream = new MemoryStream())
     {
        PdfReader = new PdfReader(stream);
        PdfDocument pdfDocument = new PdfDocument(PdfReader, new PdfWriter(returnMemoryStream));
        int numberOfPages = pdfDocument.GetNumberOfPages();

        for (int i = 1; i <= 2; i++)
                {
                    PdfPage pdfPage = pdfDocument.GetPage(i);
                    PdfCanvas canvasPage = new PdfCanvas(pdfPage);
                    switch (i)
                    {
                        case 1:
                            int versionpage1X = 735;
                            int versionpage1Y = 248;
                            canvasPage.BeginText()
                                  .SetFontAndSize(PdfFontFactory
                                       .CreateFont(StandardFonts.HELVETICA_BOLD), 34)
                                  .MoveText(versionpage1X, versionpage1Y)
                                  .SetFillColor(ColorConstants.WHITE)
                                  .ShowText(_versionNumber)
                                  .EndText();

                            break;

                        case 2:

                            int versionpage2X = 760;
                            int versionpage2Y = 573;

                            canvasPage.BeginText()                                 
                           .SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD), 21)
                                  .MoveText(versionpage2X, versionpage2Y)
                                  .SetFillColor(ColorConstants.WHITE)
                                  .ShowText(_versionNumber)
                                  .EndText();


                            float disclaimerpage2X = 75;
                            float disclaimerpage2Y = 26;


                            iText.Kernel.Geom.Rectangle rectangle = new iText.Kernel.Geom.Rectangle(disclaimerpage2X, disclaimerpage2Y, 883, 81);
                            Canvas canvas = new Canvas(canvasPage, rectangle);

                            Paragraph p = new Paragraph()
                              .Add(_disclaimer)
                              .SetFont(PdfFontFactory.CreateFont(StandardFonts.HELVETICA))
                              .SetFontColor(ColorConstants.BLACK)
                              .SetFontSize(12)
                              .SetTextAlignment(TextAlignment.LEFT);

                            canvas.Add(p);
                            canvas.Close();


                            //Image
                            float mapimageX = 111.318f;
                            float mapimageY = 130.791f;
                            float mapimageWidth = 755.454f;
                            float mapimageHeight = 432.094f;
                            ImageData imageData = ImageDataFactory.Create(@"PathtoImage.png");
                            iText.Kernel.Geom.Rectangle imagerectangle = new iText.Kernel.Geom.Rectangle(mapimageX, mapimageY, mapimageWidth, mapimageHeight);



                            canvasPage.AddImageFittedIntoRectangle(imageData, imagerectangle,true);


                            break;

                    }

                }
                pdfDocument.Close();
                b = returnMemoryStream.ToArray();
            }
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

Main

I would suggest to extract the two case branches' code into separate methods. After that your top-level functionality could be simplified like this:

using var originalPdfStream = new MemoryStream(buffer);
using var modifiedPdfStream = new MemoryStream();

var pdfReader = new PdfReader(originalPdfStream);
var pdfDocument = new PdfDocument(pdfReader, new PdfWriter(modifiedPdfStream));

EditFirstPage(pdfDocument);
EditSecondPage(pdfDocument);

pdfDocument.Close();
byte[] modifiedPdfInBytes = modifiedPdfStream.ToArray();
  • I've renamed your variables to better express the intent (like stream >> originalPdfStream)
  • I've used C# 8's using declaration to reduce code indentation
    • If you are using older C# version then you can only use here using statement

First page

void EditFirstPage(PdfDocument pdfDocument)
{
    var canvasPage = new PdfCanvas(pdfDocument.GetFirstPage());
    canvasPage.BeginText()
            .SetFontAndSize(PdfFontFactory.CreateFont(Common.Font), Page1.FontSize)
            .MoveText(Page1.Version.X, Page1.Version.Y)
            .SetFillColor(Common.FillColor)
            .ShowText(Common.VersionNumber)
            .EndText();
}
  • I've moved all the hard-coded values into a dedicated class called Page1
    • Those constants that are shared between page 1 and 2 have been moved to a class called Common
static class Common
{
    public const string Font = StandardFonts.HELVETICA_BOLD;
    public static readonly Color FillColor = ColorConstants.WHITE;
    public const string VersionNumber = "4.2021";
}

static class Page1
{
    public const int FontSize = 34;
    public static class Version
    {
        public const int X = 735, Y = 248;
    }
}

Second Page

void EditSecondPage(PdfDocument pdfDocument)
{
    var canvasPage = new PdfCanvas(pdfDocument.GetPage(2));
    canvasPage.BeginText()
        .SetFontAndSize(PdfFontFactory.CreateFont(Common.Font), Page2.FontSize)
        .MoveText(Page2.Version.X, Page2.Version.Y)
        .SetFillColor(Common.FillColor)
        .ShowText(Common.VersionNumber)
        .EndText();

    var rectangle = new Rectangle(Page2.Disclaimer.X, Page2.Disclaimer.Y, Page2.Disclaimer.Width, Page2.Disclaimer.Height);
    var canvas = new Canvas(canvasPage, rectangle);

    var paragraph = new Paragraph()
        .Add(Page2.Paragraph.Disclaimer)
        .SetFont(PdfFontFactory.CreateFont(Page2.Paragraph.Font))
        .SetFontColor(Page2.Paragraph.FontColor)
        .SetFontSize(Page2.Paragraph.FontSize)
        .SetTextAlignment(TextAlignment.LEFT);

    canvas.Add(paragraph);
    canvas.Close();
    
    ImageData imageData = ImageDataFactory.Create(Page2.MapImage.FileName);
    var imageRectangle = new Rectangle(Page2.MapImage.X, Page2.MapImage.Y, Page2.MapImage.Width, Page2.MapImage.Height);

    canvasPage.AddImageFittedIntoRectangle(imageData, imageRectangle, true);
}
  • I've renamed some variables and moved the hard-coded values into a dedicated class
static class Page2
{
    public const int FontSize = 21;
    public static class Version
    {
        public const int X = 760, Y = 573;
    }
    public static class Disclaimer
    {
        public const float X = 75, Y = 26;
        public const float Width = 883, Height = 81;
    }
    public static class MapImage
    {
        public const string FileName = "PathtoImage.png";
        public const float X = 111.318f, Y = 130.791f;
        public const float Width = 755.454f, Height = 432.094f;
    }
    public static class Paragraph
    {
        public const string Disclaimer = "Text";
        public const string Font = StandardFonts.HELVETICA;
        public static readonly Color FontColor = ColorConstants.BLACK;
        public const int FontSize = 12;
    }
}

The code which adds the version number to a specific page is redundant. You can define a helper method to that like this:

void AddVersionNumber(PdfCanvas canvasPage, int fontSize, double x, double y)
    => canvasPage.BeginText()
        .SetFontAndSize(PdfFontFactory.CreateFont(Common.Font), fontSize)
        .MoveText(x, y)
        .SetFillColor(Common.FillColor)
        .ShowText(Common.VersionNumber)
        .EndText();

For the sake of completeness here is the full code

using var originalPdfStream = new MemoryStream(buffer);
using var modifiedPdfStream = new MemoryStream();

var pdfReader = new PdfReader(originalPdfStream);
var pdfDocument = new PdfDocument(pdfReader, new PdfWriter(modifiedPdfStream));

EditFirstPage(pdfDocument);
EditSecondPage(pdfDocument);

pdfDocument.Close();
byte[] modifiedPdfInBytes = modifiedPdfStream.ToArray();
void AddVersionNumber(PdfCanvas canvasPage, int fontSize, double x, double y)
    => canvasPage.BeginText()
        .SetFontAndSize(PdfFontFactory.CreateFont(Common.Font), fontSize)
        .MoveText(x, y)
        .SetFillColor(Common.FillColor)
        .ShowText(Common.VersionNumber)
        .EndText();

void EditFirstPage(PdfDocument pdfDocument)
    => AddVersionNumber(new PdfCanvas(pdfDocument.GetFirstPage()), Page1.FontSize, Page1.Version.X, Page1.Version.Y);

void EditSecondPage(PdfDocument pdfDocument)
{
    var canvasPage = new PdfCanvas(pdfDocument.GetPage(2));
    AddVersionNumber(canvasPage, Page2.FontSize, Page2.Version.X, Page2.Version.Y);

    var rectangle = new Rectangle(Page2.Disclaimer.X, Page2.Disclaimer.Y, Page2.Disclaimer.Width, Page2.Disclaimer.Height);
    var canvas = new Canvas(canvasPage, rectangle);
    var paragraph = new Paragraph()
        .Add(Page2.Paragraph.Disclaimer)
        .SetFont(PdfFontFactory.CreateFont(Page2.Paragraph.Font))
        .SetFontColor(Page2.Paragraph.FontColor)
        .SetFontSize(Page2.Paragraph.FontSize)
        .SetTextAlignment(TextAlignment.LEFT);

    canvas.Add(paragraph);
    canvas.Close();
    
    ImageData imageData = ImageDataFactory.Create(Page2.MapImage.FileName);
    var imageRectangle = new Rectangle(Page2.MapImage.X, Page2.MapImage.Y, Page2.MapImage.Width, Page2.MapImage.Height);

    canvasPage.AddImageFittedIntoRectangle(imageData, imageRectangle, true);
}
static class Common
{
    public const string Font = StandardFonts.HELVETICA_BOLD;
    public static readonly Color FillColor = ColorConstants.WHITE;
    public const string VersionNumber = "4.2021";
}

static class Page1
{
    public const int FontSize = 34;
    public static class Version
    {
        public const int X = 735, Y = 248;
    }
}

static class Page2
{
    public const int FontSize = 21;
    public static class Version
    {
        public const int X = 760, Y = 573;
    }
    public static class Disclaimer
    {
        public const float X = 75, Y = 26;
        public const float Width = 883, Height = 81;
    }
    public static class MapImage
    {
        public const string FileName = "PathtoImage.png";
        public const float X = 111.318f, Y = 130.791f;
        public const float Width = 755.454f, Height = 432.094f;
    }
    public static class Paragraph
    {
        public const string Disclaimer = "Text";
        public const string Font = StandardFonts.HELVETICA;
        public static readonly Color FontColor = ColorConstants.BLACK;
        public const int FontSize = 12;
    }
}

UPDATE #1 using statement vs using declaration

Prior C#8 you can not use using declaration but you can use using statements

using (var originalPdfStream = new MemoryStream(buffer))
using (var modifiedPdfStream = new MemoryStream())
{
    var pdfReader = new PdfReader(originalPdfStream);
    var pdfDocument = new PdfDocument(pdfReader, new PdfWriter(modifiedPdfStream));
    
    EditFirstPage(pdfDocument);
    EditSecondPage(pdfDocument);
    
    pdfDocument.Close();
    byte[] modifiedPdfInBytes = modifiedPdfStream.ToArray();
}
\$\endgroup\$
4
  • \$\begingroup\$ I am getting error about using declarations' is not available in C# 7.3. is there another way to write that section of the code? can i just use var originalPdfStream without the using? \$\endgroup\$
    – Jefferson
    Apr 1 at 14:11
  • 1
    \$\begingroup\$ @Jefferson Please check my update \$\endgroup\$ Apr 1 at 14:14
  • \$\begingroup\$ another question I had was when I do canvas.Add(paragraph); will that add the canvasPage? I am missing the paragraph text i only have the data that is getting added to the canvasPage? \$\endgroup\$
    – Jefferson
    Apr 1 at 14:37
  • 1
    \$\begingroup\$ @Jefferson I did not touch your logic, so if it worked in your version it should work with the proposed version as well. \$\endgroup\$ Apr 1 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.