PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Sat Apr 27, 2024 12:14 pm

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Wed Nov 15, 2023 8:19 am 
Offline

Joined: Wed Nov 15, 2023 7:55 am
Posts: 5
In trying to figure out how to get the exact bounding box of a MigraDoc Table cell (so that I can then do some manual PDFSharp drawing with XGraphics), I have found that table cell borders do not actually get rendered according to the Cell.Border definition. (I might be wrong though).

The following code just creates a simple MigraDoc Document, with a 10 x 10 table.
Each cell going from left to right, top to bottom will have a border color from an array of 4 colors.
I've added text to each cell so that its easier to reference them.

The output of the below code (after being rendered) produces the following:
Image

The border shared between cell 0,0 and 0,1 is LightGreen, when it should (according to the code below) have green on the left and salmon on the right.
It looks like the previous cell's right hand border takes precedence over a cells left hand border.
Also the top and bottom borders extend into the previous cells right hand border.

Also there is an issue vertically, for example the 0,0 cell's bottom border takes precedence over the 1,0 cell's top border.

Code:
        var document = new Document();
        SetupStyles(document);
        var section = document.AddSection();
        section.PageSetup = document.DefaultPageSetup.Clone();
        section.PageSetup.PageFormat = PageFormat.A4;
        section.PageSetup.LeftMargin = section.PageSetup.RightMargin = Unit.FromCentimeter(1);
        var table = section.AddTable();
        table.Style = StyleNames.Normal;
        table.Format.Alignment = ParagraphAlignment.Center;
        table.Borders.Top.Style = table.Borders.Bottom.Style = table.Borders.Left.Style = table.Borders.Right.Style = BorderStyle.Single;
        table.Borders.Top.Width = table.Borders.Bottom.Width = table.Borders.Left.Width = table.Borders.Right.Width = Unit.FromPoint(4);

        Color[] colors = new Color[] { Colors.LightGreen, Colors.LightSalmon, Colors.LightGray, Colors.LightBlue };
        int color_index = 0;
        var width = section.PageSetup.PageWidth - (section.PageSetup.LeftMargin + section.PageSetup.RightMargin);
        for (int c = 0; c < 10; c++)
        {
            table.AddColumn(width / 10);
        }

        for (int rowIndex = 0; rowIndex < 10; rowIndex++)
        {
            var row = table.AddRow();
            for (int cellIndex = 0; cellIndex < 10; cellIndex++)
            {
                var color = colors[color_index]; //Give each cell its own border color
                row.Cells[cellIndex].Borders.Top.Color = color;
                row.Cells[cellIndex].Borders.Bottom.Color = color;
                row.Cells[cellIndex].Borders.Left.Color = color;
                row.Cells[cellIndex].Borders.Right.Color = color;
                row.Cells[cellIndex].AddParagraph($"{rowIndex},{cellIndex}");
                color_index++;
                if (color_index > 3)
                    color_index = 0;
            }
        }

        return document;


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 15, 2023 8:29 am 
Offline
PDFsharp Expert
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 916
Location: CCAA
kyro wrote:
The border shared between cell 0,0 and 0,1 is LightGreen, when it should (according to the code below) have green on the left and salmon on the right.
There is one border in one colour, not two half borders in different colours. This is by design. That's how MigraDoc is defined to work.

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 15, 2023 8:58 am 
Offline

Joined: Wed Nov 15, 2023 7:55 am
Posts: 5
If it's intended thats okay.

As I stated before I'm trying to calculate the bounding box of a cell in a table so that I can do some manual drawing using XGraphics.
Specifically I'm needing to put these plus & equals symbols on the border between cells, for select rows in the table.
Image

There isn't a property on the cells or the FormattedCells that gives its X & Y positions on the page (that I can see), so I'm finding the bounding boxes using the following code.
Is there potentially an easier way to do this?

Code:
DocumentRenderer renderer = new DocumentRenderer(document); //MigraDoc Document created from somewhere else.
renderer.PrepareDocument();

PdfDocument pdf = new PdfDocument();
var pages = renderer.FormattedDocument!.PageCount;
for (int i = 1; i <= pages; i++)
{
    var page = pdf.AddPage();
    var gfx = XGraphics.FromPdfPage(page);
    renderer.RenderPage(gfx, i);
    var renderInfos = renderer.GetRenderInfoFromPage(i) ?? Array.Empty<RenderInfo>();
    renderer.PrepareDocument();
    foreach (var tableRenderInfo in renderInfos.OfType<TableRenderInfo>())
    {
        if (tableRenderInfo.DocumentObject is Table table && tableRenderInfo.FormatInfo is TableFormatInfo tableFormatInfo && tableFormatInfo.FormattedCells is not null)
        {
            var y = tableRenderInfo.LayoutInfo.ContentArea.Y.Point;
            XColor[] colors = new XColor[] { XColors.Blue, XColors.Red };
            int color_index = 0;

            foreach (Row row in table.Rows)
            {
                if (row.Index == 0)
                {
                    y += row.Borders.Top.Width.Point / 2; //move Y point into middle of Row's top Border
                }
                //Calculate the maximum inner height from all the cells in the row
                //Cant just look at the first cell, because of how the cell's inner heights are calculated
                double row_max_inner_height = 0;
                foreach (Cell cell in row.Cells)
                {
                    var formattedCell = tableFormatInfo.FormattedCells[cell];
                    var innerHeight = formattedCell.GetInnerHeight().Point;
                    row_max_inner_height = Math.Max(innerHeight, row_max_inner_height);
                }
                var x = tableRenderInfo.LayoutInfo.ContentArea.X.Point;

                double new_y = y + (row.Borders.Top.Width.Point / 2) + row_max_inner_height + (row.Borders.Bottom.Width.Point / 2);

                foreach (Cell cell in row.Cells)
                {
                    if (cell.Column.Index == 0)
                    {
                        x += cell.Borders.Left.Width.Point / 2; //move X point into middle of Cell's left border
                    }
                    double inner_width = tableFormatInfo.FormattedCells[cell].GetInnerWidth().Point;


                    XPoint top_left = new XPoint(x, y);
                    x += (cell.Borders.Left.Width.Point / 2) + inner_width + (cell.Borders.Right.Width.Point / 2); //moves X to middle of next Cell's left border
                    XPoint bottom_right = new XPoint(x, new_y);

                    var pen = new XPen(colors[color_index], 2);
                    gfx.DrawRectangle(pen, new XRect(top_left, bottom_right)); // Just for testing, draw a new Rectangle around each cell
                    color_index++;
                    if (color_index > 1)
                        color_index = 0;
                }
                y = new_y;
            }
        }
    }
}


Top
 Profile  
Reply with quote  
PostPosted: Wed Nov 15, 2023 10:39 am 
Offline
PDFsharp Expert
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 916
Location: CCAA
It makes no sense to call "GetRenderInfoFromPage(i)" before calling "PrepareDocument". Makes no sense to call "renderer.PrepareDocument();" in the loop.

I don't know which render information there is for cells or borders.
You can get render information for the paragraphs in the cells.

Since you set the widths of the columns in your code, it should be quite easy to determine the X position for the vertical borders. The Y position can be taken from a paragraph in the same row.

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 404 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group