Hi everyone,
I spent the whole day trying to find out why one of my MigraDoc tables is showing weird borders.
Finally, I managed to create a bugfix and want to let the developers know about it.
Because my original table is pretty large, I broke the little nasty bug down to a smaller table like this one:
Code:
Document document = new Document();
Section section = document.AddSection();
Table table = section.AddTable();
Column col = table.AddColumn();
col.Borders.Left.Width = 2;
col = table.AddColumn();
col.Borders.Left.Color = Colors.Red;
col.Borders.Left.Width = 1;
Row row = table.AddRow();
row = table.AddRow();
row.Borders.Top.Width = 2;
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true, PdfFontEmbedding.Always);
renderer.Document = document;
renderer.RenderDocument();
string filename = "TheBug.pdf";
renderer.PdfDocument.Save(filename);
Process.Start(filename);
The table contains two columns and two rows.
The two columns each have different borders on the left hand; I used a black 2px border for the first, and a red 1px border for the second column, so we can easily distinguish between them.
Then I added two rows, one without any changes, the other one with a top border been set. This is important, because changing any(!) border of a row causes the bug to occur.
--------
Now let's talk about the results. I expected the pdf to look like this:
Attachment:
withoutbug.PNG [ 895 Bytes | Viewed 9204 times ]
But in fact it looked like this:
Attachment:
withbug.PNG [ 1.15 KiB | Viewed 9204 times ]
So I downloaded the source and started to dig down, trying to find out what's wrong with this table.
I finally found the bug deep in the source of MigraDoc.DocumentObjectModel.Visitors\VisitorBase.cs
I have been using version 1.32 for bugfixing, but the bug appears in the latest 1.50 beta as well.
Please note this information, I can't guarantee that the line numbers are still valid for 1.50 beta.
---------
To eliminate the bug, open VisitorBase.cs, go to line 797 in the VisitTable-method.
Change:
Code:
if (cell.borders == null)
cell.borders = row.borders;
else if (row.borders != null)
FlattenBorders(cell.borders, row.borders);
if (cell.borders == null)
cell.borders = column.borders;
else if (column.borders != null)
FlattenBorders(cell.borders, column.borders);
to that:
Code:
if (row.borders != null)
FlattenBorders(cell.Borders, row.borders);
if (column.borders != null)
FlattenBorders(cell.Borders, column.borders);
The reason why, should be pretty obvious.
For example: In a row, where every cell's border has not been set (is null), 'cell.borders = row.borders;' is called for each cell in this row. Unfortunately, this will set the cell's border to a pointer of the row's border. Each cells border is now identical, so each cell looks the same.
In my case, I wanted the cells to get their border information from the corresponding columns, so I got the weird result.
I wonder why this hasn't already been discovered and fixed by someone.