From 4b105e0b1f4e68d427e3f37e5a7daaf6cc762141 Mon Sep 17 00:00:00 2001 From: Vitali Prudnikovich Date: Tue, 16 Apr 2024 11:56:54 +0000 Subject: [PATCH] =?UTF-8?q?=EF=BB=BFFix=20empty=20row=20elimination=20logi?= =?UTF-8?q?c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEVSIX-6095 Autoported commit. Original commit hash: [25cfbd9d0] --- .../itext/layout/TableTest.cs | 30 ++++-- .../cmp_tableWithAlternatingRowsTest.pdf | Bin 2350 -> 2545 bytes .../cmp_tableWithCollapsedBordersTest.pdf | Bin 1096 -> 1276 bytes ..._tableWithEmptyRowAfterJustOneCellTest.pdf | Bin 1081 -> 1312 bytes .../cmp_tableWithEmptyRowsAndSpansTest.pdf | Bin 0 -> 1338 bytes ..._tableWithEmptyRowsBetweenFullRowsTest.pdf | Bin 1083 -> 1269 bytes .../layout/renderer/CollapsedTableBorders.cs | 14 +-- .../itext/layout/renderer/TableBorders.cs | 101 ++++++++++++------ port-hash | 2 +- 9 files changed, 89 insertions(+), 58 deletions(-) create mode 100644 itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowsAndSpansTest.pdf diff --git a/itext.tests/itext.layout.tests/itext/layout/TableTest.cs b/itext.tests/itext.layout.tests/itext/layout/TableTest.cs index 55158a0e29..252afce70e 100644 --- a/itext.tests/itext.layout.tests/itext/layout/TableTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/TableTest.cs @@ -1696,7 +1696,6 @@ public virtual void TableWithEmptyLastRowTest() { } [NUnit.Framework.Test] - [LogMessage(iText.IO.Logs.IoLogMessageConstant.UNEXPECTED_BEHAVIOUR_DURING_TABLE_ROW_COLLAPSING)] public virtual void TableWithEmptyRowsBetweenFullRowsTest() { String testName = "tableWithEmptyRowsBetweenFullRowsTest.pdf"; String outFileName = destinationFolder + testName; @@ -1716,8 +1715,6 @@ public virtual void TableWithEmptyRowsBetweenFullRowsTest() { } [NUnit.Framework.Test] - [LogMessage(iText.IO.Logs.IoLogMessageConstant.UNEXPECTED_BEHAVIOUR_DURING_TABLE_ROW_COLLAPSING, Count = 2 - )] [LogMessage(iText.IO.Logs.IoLogMessageConstant.LAST_ROW_IS_NOT_COMPLETE)] public virtual void TableWithEmptyRowAfterJustOneCellTest() { String testName = "tableWithEmptyRowAfterJustOneCellTest.pdf"; @@ -1739,8 +1736,6 @@ public virtual void TableWithEmptyRowAfterJustOneCellTest() { } [NUnit.Framework.Test] - [LogMessage(iText.IO.Logs.IoLogMessageConstant.UNEXPECTED_BEHAVIOUR_DURING_TABLE_ROW_COLLAPSING, Count = 39 - )] [LogMessage(iText.IO.Logs.IoLogMessageConstant.LAST_ROW_IS_NOT_COMPLETE)] public virtual void TableWithAlternatingRowsTest() { String testName = "tableWithAlternatingRowsTest.pdf"; @@ -1782,8 +1777,27 @@ public virtual void ColoredTableWithColoredCellsTest() { } [NUnit.Framework.Test] - [LogMessage(iText.IO.Logs.IoLogMessageConstant.UNEXPECTED_BEHAVIOUR_DURING_TABLE_ROW_COLLAPSING, Count = 2 - )] + public virtual void TableWithEmptyRowsAndSpansTest() { + String testName = "tableWithEmptyRowsAndSpansTest.pdf"; + String outFileName = destinationFolder + testName; + String cmpFileName = sourceFolder + "cmp_" + testName; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc); + Table table = new Table(UnitValue.CreatePercentArray(new float[] { 30, 30, 30 })); + table.AddCell(new Cell().Add(new Paragraph("Hello"))); + table.AddCell(new Cell().Add(new Paragraph("Lovely"))); + table.AddCell(new Cell().Add(new Paragraph("World"))); + StartSeveralEmptyRows(table); + table.AddCell(new Cell(2, 2).Add(new Paragraph("Hello"))); + table.AddCell(new Cell().Add(new Paragraph("Lovely"))); + table.AddCell(new Cell().Add(new Paragraph("World"))); + doc.Add(table); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , testName + "_diff")); + } + + [NUnit.Framework.Test] public virtual void TableWithEmptyRowsAndSeparatedBordersTest() { String testName = "tableWithEmptyRowsAndSeparatedBordersTest.pdf"; String outFileName = destinationFolder + testName; @@ -1804,8 +1818,6 @@ public virtual void TableWithEmptyRowsAndSeparatedBordersTest() { } [NUnit.Framework.Test] - // TODO DEVSIX-6020:Border-collapsing doesn't work in case startNewRow has been called - [LogMessage(iText.IO.Logs.IoLogMessageConstant.UNEXPECTED_BEHAVIOUR_DURING_TABLE_ROW_COLLAPSING)] public virtual void TableWithCollapsedBordersTest() { String testName = "tableWithCollapsedBordersTest.pdf"; String outFileName = destinationFolder + testName; diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithAlternatingRowsTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithAlternatingRowsTest.pdf index 452bb1c533472620a29762035e44a846336bc46c..e3ea693bb9c600fcd8bf35caf1c0c92fa996ab8b 100644 GIT binary patch delta 1777 zcmc&z`#V&57CWm1YO&>3RAC_WRTOyzl3IKcCP0KHqZfNu4xUKqA@O z^Fu?pXnbXzl8dN}oT8@o5r05Ls1v?Cq#!q>PTCkyDe>!NI$uQsLwNfaz*mS%9Tl zGdo-m^LFaZv(t6EpY8x_OB19FL5x93^VfELsUvnCzmAVQ3ik?Hdtv-ZpvY2EaHldl z%lJy3wW0O0!&AXFCG33ty4fDRh{?XL)*(^3dpfgg#@s!S7AC1ynS%(ox7$6zq>Ki& z-afW{ZAGaNlU>VBYac7NtdAN8v*kQ1+GPcG_Zhm%Dz7u?fdbl;w`pDLkq}>I>p9b_ z*+Mx~QXer7J;v;so2F;BQjQ%T9hvE@p2gafxaR+Tbc>N(n@VrL4yjhJ+os~@=uWxV zsE#4u5xM%Mut%71dMMoMspIXL0(s$_%zKuP7WS~2FE5D7?IS1qJnaRYsfQaJ6QWxZ z?pJy;t!MllDYAX_WzQ#GBya~M1Fl0C2xVa%qx2aIo4r2kGpuC4Wn8H792+B5CzSnx z@2*f%W%2kIPw#b*(Y-`3W0bntPD3ravc=0Km zGVl0Jy0dO#UE`u9I0b=WzJtMiwsnrn&P$0K{NnLvi%!+0Z`$T}PA3o_n z^Eh@Q+2|v+ljwHJ%+`6Je)966ExmX*!MwN5d*%a0t^9%o-{+fq@C&w)H-Ax@iMg}W)$Wpqj`P4l{R@Ub7q`zNj)L&aSN`U4s_0TeO$lD z`juAt{NgBma8)1w-R{BiXKq`S!*4rkL}r}S9;xs+d}1IU^0V?V+2F4_aJPs(T>dO6 zSJ4J26tAzL^K-Frm87y zyY$uQFrT{r+l=8Gu}34WT~RAEUbeI8Zi5{#wp@^wP!t{Q*NaPR>iBN@Z7?CeJ;gGp zS5TB9>3VUD_|23ns_+!f$`MZKwmDvkVpz$h+T)Tg`$|Fv*8GsTvUsx*kYA(ryg5x& z*y0+*i7QI=Y4V%a#B{~#sou1di|lPBTX|LbxSV@>hQFuALkVph+O>7}Ryw$ly>c`R zHd;+cU;5WtnlQ*vzNwQDb&I&ZUl%@^y7HH$XWLUlhmlZPQdQoDTa{dqV)Vc|2)m_{ zf&HkeX8{2a2mn-=2twun$ru2PO|9I5I8JCN*Tl)12oOI5V7;pAR1izR62fLw4YVP` z=HQS>K9@iX2?`4)xO>~scH0J^Uq(Y=Ga%2+nMGo7nu7f$M zuQr9hD8ay&IS@jySoJjm04AXT1?55@k;owfM3@32Fqs6is3d@lf?NPaP!Qm-$p8!? z95NY(C=kjc^8gM4vp@>K=1^HAluIVDn2hic4vO%&ESM-C z2XHwQkcWaSgh&Mu7=i>`d)xn0!Xmi_F4m`RX)t%7O`h(XcX@87duj4R(U8!H5H3%X OC_jXzq2V^Vv*v#ieD`qx delta 1584 zcmew;yiRC>X}yV&on3KBQEFl?SH+y(=_mU{3HZiL_p0ki5o^>Vb~e6@ z3mH2;{7%_soZCEO#TAdme40ver(?@3=WpM>{q5P`8`^i=-EO*}y-mCj|Cf$41{dCGxX161N3W&7DI{!Uv~{G8gA?LT)} zY7@0DlY#|1Dh(F@$n4MjQH^S`CBTU#oC>1+Z|WXUfJ)z`QehhcU$%| zxBa}IwEy${=lrvmpSvHuXtKilv(x`BuX!e{`=IA3G zi}7Mf%0Vzv-5%zfmWv;;4uz*##v;rtNsX2uLg7448aV;=f$c*#wLq+W+)yj zJSRWL{_wZFX;}}R-E&&MuClJ<$XlsEhBF3_7f9yLlUIV;b>xWhGniclhcCC-%vXgP zZy2=n=$z;69w#IO6Cdyx7d_NI2v?|l(Zl>aKSW_YkFnE(&Ju%N5O;J4O7mX%yiH?HnE5_2;Gs-{5Jb}hlkIF4yA-PiHA8hyR_gz{I%}5 z99&mQ)ajqe9Z+vh1bWj_3F6H}w!52eJJ`6pB(=FsVKlbM7LhACzM?R^;?jf$KQoPk zG`_fPp!Da@cyUPW=Ge8M(8nK7M6wOf@a@`nGBEpZnisZ`pSLR(ba= zDogqD?gI>dK_LPG%bIso)}s;@ z!fkv^zN?Q{Ipqo%_|$_KYekM^ezw}D_f6!$tjN!4f5X?NRL+xcIdx6HQLbmQV`XK| z`*|W2y5b){-Jj?4@p^6T^Y1S{-(cLi%l-Cw?>gRtd@kBe9pN+XENDo`$lWqIca2B( z2cOIeRuT8b^J*3=?>%U=bYgvuOy~S=eUk<37K?tA{_{J-ab>c8$r2Uy2sQJXBahzo zmTl@4&E%b@+52ZXcb&63-nbtk8>$#NSS8W@=wni!ZF z7*6hE6GP#zXOm+!*E7;HoP3E*MbJ}U8Je0S#7c@1GjmdlxNL0nJzW%{ zZA^?3(^8DmjM9=UQ<74R3{%a`QcW$4EDTI75{*nuQta@kV1p=`JfBlf1?*kjU_Zxz eU=RNguHur!qLPZD)HE(bOG|SuRaIAiH!c7nIlE#2 diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithCollapsedBordersTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithCollapsedBordersTest.pdf index 4c4e684a0aa6967d39a2ca1cf8b8c43674d9d99b..1cde41cd88cc30949e4722458a4c7c84ed0dc2a3 100644 GIT binary patch delta 709 zcmX@X@rQGQX}y7=on3KBQEFl?SH+y({@r|s40v42>s{Ro@0y7K@%#92qp$FvN^3j3*Z}t1%fH zPoB*zRc~mSlxC5bY>}FnVriIcmSUc2YL;xCXpxj^nP!q~nw(@{oMw?`mYQr~X_RJ^ zYMNwWXl#^dVr*h;Y?NYQXkl(*oSd4Jl5Ap`Xli6?U}BtVo|Mt0VU(6;m}qDTG%3jls1_(>oLHY`XETsaU;(-zZSr?!J!No^>jwKd1_XQf bhj0~_Bo>ua6s4wdnVTDNsj9mAyKw;k?PKSQ delta 508 zcmeyvd4gktX}zI|on3KBQEFl?SH+y(2|M`?8Su1~+q=3&^vqrC7p~GL+Hr(ige{~c z;o(=$DGvNwg-!{1-><*nAHg1x8@Vy;A=k0R!9l`Ri=CLe|1QmyKV8u5+rVtoz9GV7 zoBw?I_1k7H-n{kei@WjHLcYJ;Xu9%CpY?(lzu1BomYoV-`tE6xep}%6Rjrpr^sRoT z+xib$cdrGESfD!=yWT0i&#r zp`n41xuKDXg|UgYfw8)Qfx4!?Z+?nPVo9ooi zWQL?xlqk3t<(C#H_=Ras&S%1QVo^y&QED2OxrGUrs;aBM8y5gjt*>YR diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowAfterJustOneCellTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowAfterJustOneCellTest.pdf index 602d5bf1db4cde4a08362372f42f919ec4dcc330..bf5ee52c5583afc3e09637763e71f1b4c179d812 100644 GIT binary patch delta 757 zcmdnVv4CrWNxhM=xt(2cNl|KIE?32z-U+*dm<@Sct7}`mGFo!h{>hlhc!})~r^7*= z$(~d1AHTPCvPkER!pGLd{iSP^ZNw|8N?+Ja%b(!VWoWE=@DnHh?)8;+Hq+!QG&i(A zUR&g$@~hsmXmxJxdVhZ}&Ahs*3!uSehCc8fY6Bs~Z@oYwG*vr?@1R zq-wZW85tO1QxH&;pHiBfTBMN~l3G!+PQf|9C{@8i&p^*)vN@BAkcon0K~ZIKs)Bn_ zerbV%Uzq0PDU9Zm%b3>Nn;DrX7=VC6o&pz`VPIfxYK|dhVrqmTW^8CVIfYq`$;@(c z53^LgVWLs8VTx&*acZK0p{ZF)DhQjIniwaVnbnjB%7rsrkN%hrkGe5rkSRt zB%2r-0xd8|GBL6+Ni#P$H%Lk|G_XjkPqMQaNGGrW-HSwE;zk<59Id|{XYx(_m@&&PNjAqq~eU=`QJ)x-mQA&1YLF?6z*G$%zRvgefzb`rF<@&1M=h!b4wwq5l8qziOa+vMs$VX+f zLYb#)%ExCI`5)h;Cat@;;C$!)r+dWRBTk-wzUjeQw~x*5Pw#xoD$6hU{_=S(w_SoC zdrf>iLMt8kp8Q*SV1~`XfT+|tKNz~#POP7-%Q$^<0h8|JBaE^-hK7a)hK9z*W(FqO z2FB_J2I`vnzWFIGi6yBTE>=bcMo0=K^D@b?n(GDaod(7Un5Qh9)K^$#w))Og_(|rwsOn iZm^$YK(L2@2v>1QVo^y&QED2OxtS%Gs;aBM8y5hTQoI)c diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowsAndSpansTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowsAndSpansTest.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b0fbec2a39809fd85d77a52a90513fd0cf84b60d GIT binary patch literal 1338 zcmc&zZ)_Ar6sOieSomPoMBsx?luNHA*PY#+{d3wJx!(0kYw4ZWQZAGRW_M?gCD+|{ zcdr%{2;iS!QbPzB6E#hmD5)_GN=P6A!iR>05YTF)BGD9VL?I-NsWAqOGw0C@H1VtN z!|u$R_ul;8@AoE@Nv0w~gUW@j-?;KMCj$sveLL6K$fxW=Ks-KGzyV1T!!-%tPMmzO z4Ty>qi}`^^a344H{_vqsJF11{Z@j#=IhAXF{KA0KTn~>es-1l#Qr%XpPt>^Sw^yG5 zbCbWlllyD!FaE1bPChez=X}_h`m^fEgGZLHsva9yrlvn%arB4TCzR(-pPSy3d-UFy zAB`Nn(eU>t6T`DBn%>(pa`yTk*=tKypB>%Ry=Ag@?&>vRarD;c)ZH_&eI0#Y>}}lC z9e?EnpKpC?dw0!`muFu8>eQht`K7O29iJHCeHVV$_VZ}^VA@Vi-#$FJ z@#5UdOUJfv`@37F?!8o>Y5BEg!^h7~jKz0XZJoK0OM*4FXsUGu*KGM;M|4dR9E zE;1C1gM{l5pf$h-6zS}UXFAuVyTImfyd~2P28rj>3pdw+F%d!-VON59zqi9Dpv7~G z{h*_}u7XvlU}a7CWhzQtC2)WXZoU%Cs3N5K86Xq7F9s>WOZTdY-&1~<#86|X;lp&8;90V#ydn_AJ zWLc7d1@8M4nQF}pIP*SLqv|~5L#npGCm}jE55+-Yp--WcG#?ju*e(!{z2nv-=xLM{ zOCSiVQL4J7TAC&b1j^VlEL|ijHZ7tm7SW;ziCEGx5oK&fHAzPFSkVMilT}HFkY4|E?`e0%V%Ae nYFk=%+B*qQsh*+INJrR2M;@GL&JVB`l!VqK#Dzl5=@j=5>Q}2r literal 0 HcmV?d00001 diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowsBetweenFullRowsTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableWithEmptyRowsBetweenFullRowsTest.pdf index d17b88bf629b5e5bffdb6b24750827b18d6b0330..aad3d0b530e3656d138e8773c127b4ff89308624 100644 GIT binary patch delta 684 zcmdnZ@s)FeNxh+^iJe_>Nl|KIE?32z-hNBILk0q_zb#w6GuYlIZ}-sAP3Yui;Ytx{ zZF~J#;~bL`+s>K#`|Z!?CCDah74`8DTem<)%5C1_V4aW+H{z4lOn=BWn}I#!UgD({ zU#8ey?~gcp@ov`ZfSLQl`@cNTI(Mu14x@kc`~^B*hh?_EnV0Ur>80Cdj^+6_o=@yP z-;H_3s{Tbwyhy`*itiRjqq&NI)sF8J=PapO!|^U)hy2_p3d;j7Jvg!Pg@o44z;|2v zz65?+ytq5nJ^rQa<#XI$7T4!a=46~c`7EQXj){SZp@D&=sgZ$&wt=y_fq}ZFzHfet zOJYf?hKrSvff15|$zn`$tQL9(dM1-CnN);K6dVhRDvMJU+>7!{3l#jqG$&7EG@o3- zwBFv-!cf5g1QhZVxWEhp19L+Y3^5Y}OAIk1bF;~5%xX+VW|RAvrRojLj8cp(3@uZQ zl8p=!4O5I$4NX!FlFd_6lFTfO4J=J86D`eBQ;ZA^4blvZ%`FoR3{A}pOwCNwQj<)~ z(o7RmQ!G-96Vp->4a`gplaehBQc^6;jSZ3w6O#>1%`K8llT!^+jZ%{h%#th(fs$s1 zK$eM#sX?M;Vscu&xt+~GI)Me~2J^|UnDvyw0k0eE=NJ&|;UB_PT#{H+Qc;we#$|41 M%B8C6>hHz{0PjWK<^TWy delta 519 zcmey$xtn8xNxhMQp`BfENl|KIE?32z-U&PT4jBlz{Qk=|{eq5N()znfgl6YM z7HgRNvFm#yqmVRVw(QTdXR@Lrsv~k)g(v;g*65x!@o|ReXH%VT(**5O^HxO2uk{)4mVHS#Nxy6TuHpC zl^|*i z-@!@Nr{=9wp4WEg#>AAJi?@H-KC3G3n`C|dWG2SxlU~#ZD6c!V4$w4A5fH^QktAvq>&ktT2Zo2!8yMuRl!`(NY8LGE0YSlp#oTZ zvLTbmNX6B?8 zaoO1Dd%7q@+a#GABqdoU85o!(r6pRVq!}a`n5S5nr5U9fn 0 && rows.Count != nextCellRow && (j + (int)rows[nextCellRow][j].GetPropertyAsInteger(Property. COLSPAN) != col || (int)nextCellRow - rows[(int)nextCellRow][j].GetPropertyAsInteger(Property.ROWSPAN) - + 1 + rowspansToDeduct[j] != row)); + + 1 != row)); // process only valid cells which hasn't been processed yet if (j >= 0 && nextCellRow != rows.Count && nextCellRow > row) { CellRenderer nextCell = rows[nextCellRow][j]; - nextCell.SetProperty(Property.ROWSPAN, ((int)nextCell.GetPropertyAsInteger(Property.ROWSPAN)) - rowspansToDeduct - [j]); - int nextCellColspan = (int)nextCell.GetPropertyAsInteger(Property.COLSPAN); - for (int i = j; i < j + nextCellColspan; i++) { - rowspansToDeduct[i] = 0; - } BuildBordersArrays(nextCell, nextCellRow, true); } } @@ -309,12 +303,6 @@ protected internal override void BuildBordersArrays(CellRenderer cell, int row, } if (nextCellRow != rows.Count) { CellRenderer nextCell = rows[nextCellRow][col + currCellColspan]; - nextCell.SetProperty(Property.ROWSPAN, ((int)nextCell.GetPropertyAsInteger(Property.ROWSPAN)) - rowspansToDeduct - [col + currCellColspan]); - int nextCellColspan = (int)nextCell.GetPropertyAsInteger(Property.COLSPAN); - for (int i = col + currCellColspan; i < col + currCellColspan + nextCellColspan; i++) { - rowspansToDeduct[i] = 0; - } BuildBordersArrays(nextCell, nextCellRow, true); } } diff --git a/itext/itext.layout/itext/layout/renderer/TableBorders.cs b/itext/itext.layout/itext/layout/renderer/TableBorders.cs index d1a825b263..8a506175d3 100644 --- a/itext/itext.layout/itext/layout/renderer/TableBorders.cs +++ b/itext/itext.layout/itext/layout/renderer/TableBorders.cs @@ -156,6 +156,7 @@ protected internal abstract iText.Layout.Renderer.TableBorders ApplyCellIndents( protected internal abstract float GetCellVerticalAddition(float[] indents); // endregion + [System.ObsoleteAttribute(@"Remove rowspansToDeduct parameter which is not used anymore.")] protected internal abstract void BuildBordersArrays(CellRenderer cell, int row, int col, int[] rowspansToDeduct ); @@ -166,7 +167,6 @@ protected internal abstract iText.Layout.Renderer.TableBorders UpdateBordersOnNe // endregion protected internal virtual iText.Layout.Renderer.TableBorders ProcessAllBordersAndEmptyRows() { CellRenderer[] currentRow; - int[] rowspansToDeduct = new int[numberOfColumns]; int numOfRowsToRemove = 0; if (!rows.IsEmpty()) { for (int row = startRow - largeTableIndexOffset; row <= finishRow - largeTableIndexOffset; row++) { @@ -174,26 +174,17 @@ protected internal virtual iText.Layout.Renderer.TableBorders ProcessAllBordersA bool hasCells = false; for (int col = 0; col < numberOfColumns; col++) { if (null != currentRow[col]) { - int colspan = (int)currentRow[col].GetPropertyAsInteger(Property.COLSPAN); - if (rowspansToDeduct[col] > 0) { - int rowspan = (int)currentRow[col].GetPropertyAsInteger(Property.ROWSPAN) - rowspansToDeduct[col]; - if (rowspan < 1) { - ILogger logger = ITextLogManager.GetLogger(typeof(TableRenderer)); - logger.LogWarning(iText.IO.Logs.IoLogMessageConstant.UNEXPECTED_BEHAVIOUR_DURING_TABLE_ROW_COLLAPSING); - rowspan = 1; - } - currentRow[col].SetProperty(Property.ROWSPAN, rowspan); - if (0 != numOfRowsToRemove) { - RemoveRows(row - numOfRowsToRemove, numOfRowsToRemove); - row -= numOfRowsToRemove; - numOfRowsToRemove = 0; - } + if (0 != numOfRowsToRemove) { + // Decrease rowspans if necessary + UpdateRowspanForNextNonEmptyCellInEachColumn(numOfRowsToRemove, row); + // Remove empty rows + RemoveRows(row - numOfRowsToRemove, numOfRowsToRemove); + row -= numOfRowsToRemove; + numOfRowsToRemove = 0; } - BuildBordersArrays(currentRow[col], row, col, rowspansToDeduct); + BuildBordersArrays(currentRow[col], row, col, null); hasCells = true; - for (int i = 0; i < colspan; i++) { - rowspansToDeduct[col + i] = 0; - } + int colspan = (int)currentRow[col].GetPropertyAsInteger(Property.COLSPAN); col += colspan - 1; } else { @@ -204,17 +195,14 @@ protected internal virtual iText.Layout.Renderer.TableBorders ProcessAllBordersA } if (!hasCells) { if (row == rows.Count - 1) { - RemoveRows(row - rowspansToDeduct[0], rowspansToDeduct[0]); + RemoveRows(row - numOfRowsToRemove, numOfRowsToRemove); // delete current row - rows.JRemoveAt(row - rowspansToDeduct[0]); + rows.JRemoveAt(row - numOfRowsToRemove); SetFinishRow(finishRow - 1); ILogger logger = ITextLogManager.GetLogger(typeof(TableRenderer)); logger.LogWarning(iText.IO.Logs.IoLogMessageConstant.LAST_ROW_IS_NOT_COMPLETE); } else { - for (int i = 0; i < numberOfColumns; i++) { - rowspansToDeduct[i]++; - } numOfRowsToRemove++; } } @@ -226,17 +214,6 @@ protected internal virtual iText.Layout.Renderer.TableBorders ProcessAllBordersA return this; } - private void RemoveRows(int startRow, int numOfRows) { - for (int row = startRow; row < startRow + numOfRows; row++) { - rows.JRemoveAt(startRow); - horizontalBorders.JRemoveAt(startRow + 1); - for (int j = 0; j <= numberOfColumns; j++) { - verticalBorders[j].JRemoveAt(startRow + 1); - } - } - SetFinishRow(finishRow - numOfRows); - } - // region init protected internal virtual iText.Layout.Renderer.TableBorders InitializeBorders() { IList tempBorders; @@ -419,6 +396,60 @@ public virtual float[] GetCellBorderIndents(int row, int col, int rowspan, int c } return indents; } + // endregion + private void RemoveRows(int startRow, int numOfRows) { + for (int row = startRow; row < startRow + numOfRows; row++) { + rows.JRemoveAt(startRow); + horizontalBorders.JRemoveAt(startRow + 1); + for (int j = 0; j <= numberOfColumns; j++) { + verticalBorders[j].JRemoveAt(startRow + 1); + } + } + SetFinishRow(finishRow - numOfRows); + } + + private void UpdateRowspanForNextNonEmptyCellInEachColumn(int numOfRowsToRemove, int row) { + // We go by columns in a current row which is not empty. For each column we look for + // a non-empty cell going up by rows (going down in a table). For each such cell we + // collect data to be able to analyze its rowspan. + // Iterate by columns + int c = 0; + while (c < numberOfColumns) { + int r = row; + CellRenderer[] cr = null; + // Look for non-empty cell in a column + while (r < rows.Count && (cr == null || cr[c] == null)) { + cr = rows[r]; + ++r; + } + // Found a cell + if (cr != null && cr[c] != null) { + CellRenderer cell = cr[c]; + int origRowspan = (int)cell.GetPropertyAsInteger(Property.ROWSPAN); + int spansToRestore = 0; + // Here we analyze whether current cell's rowspan touches a non-empty row before + // numOfRowsToRemove. If it doesn't touch it we will need to 'restore' a few + // rowspans which is a difference between the current (non-empty) row and the row + // where we found non-empty cell for this column + if (row - numOfRowsToRemove < r - origRowspan) { + spansToRestore = r - row - 1; + } + int rowspan = origRowspan; + rowspan = rowspan - numOfRowsToRemove; + if (rowspan < 1) { + rowspan = 1; + } + rowspan += spansToRestore; + rowspan = Math.Min(rowspan, origRowspan); + cell.SetProperty(Property.ROWSPAN, rowspan); + int colspan = (int)cell.GetPropertyAsInteger(Property.COLSPAN); + c += colspan; + } + else { + ++c; + } + } + } } } diff --git a/port-hash b/port-hash index eebc9c8ba8..d2a74f8d0a 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -daafb56864e655e3de3fbf76865c017b57edb51d +a57e64266d366bfcf87f8c3045b77a96db1cf373