@@ -2993,19 +2993,40 @@ private static void RenderTable(RenderState state, DocxTable table)
29932993 var isLastCell = cellGridEnd >= colCount ;
29942994 var borders = cell . Borders ;
29952995
2996+ // Suppress horizontal borders inside vertically-merged cell groups:
2997+ // - vMerge continue cells: suppress top border (internal to merge)
2998+ // - Any cell whose next row continues the merge at the same column: suppress bottom border
2999+ var suppressTop = cell . IsVMergeContinue ;
3000+ var suppressBottom = false ;
3001+ if ( cell . IsVMergeRestart || cell . IsVMergeContinue )
3002+ {
3003+ // Check if the next row has a vMerge continue at the same column
3004+ var nextRowIdx = rowIndex + 1 ;
3005+ if ( nextRowIdx < table . Rows . Count )
3006+ {
3007+ var nci = 0 ;
3008+ foreach ( var nc in table . Rows [ nextRowIdx ] . Cells )
3009+ {
3010+ if ( nci == bci ) { suppressBottom = nc . IsVMergeContinue ; break ; }
3011+ nci += nc . GridSpan ;
3012+ if ( nci > bci ) break ;
3013+ }
3014+ }
3015+ }
3016+
29963017 // Resolve each border: prefer cell-level, fall back to table-level
29973018 DocxBorderEdge ? topBorder , bottomBorder , leftBorder , rightBorder ;
29983019 if ( borders != null )
29993020 {
3000- topBorder = borders . Top ?? ( table . HasBorders ? ( isFirstRow ? table . BorderTop : table . BorderInsideH ) : null ) ;
3001- bottomBorder = borders . Bottom ?? ( table . HasBorders ? ( isLastRow ? table . BorderBottom : table . BorderInsideH ) : null ) ;
3021+ topBorder = suppressTop ? null : ( borders . Top ?? ( table . HasBorders ? ( isFirstRow ? table . BorderTop : table . BorderInsideH ) : null ) ) ;
3022+ bottomBorder = suppressBottom ? null : ( borders . Bottom ?? ( table . HasBorders ? ( isLastRow ? table . BorderBottom : table . BorderInsideH ) : null ) ) ;
30023023 leftBorder = borders . Left ?? ( table . HasBorders ? ( isFirstCell ? table . BorderLeft : table . BorderInsideV ) : null ) ;
30033024 rightBorder = borders . Right ?? ( table . HasBorders ? ( isLastCell ? table . BorderRight : table . BorderInsideV ) : null ) ;
30043025 }
30053026 else if ( table . HasBorders )
30063027 {
3007- topBorder = isFirstRow ? table . BorderTop : table . BorderInsideH ;
3008- bottomBorder = isLastRow ? table . BorderBottom : table . BorderInsideH ;
3028+ topBorder = suppressTop ? null : ( isFirstRow ? table . BorderTop : table . BorderInsideH ) ;
3029+ bottomBorder = suppressBottom ? null : ( isLastRow ? table . BorderBottom : table . BorderInsideH ) ;
30093030 leftBorder = isFirstCell ? table . BorderLeft : table . BorderInsideV ;
30103031 rightBorder = isLastCell ? table . BorderRight : table . BorderInsideV ;
30113032 }
@@ -3074,7 +3095,11 @@ private static void RenderTable(RenderState state, DocxTable table)
30743095 // to the row bottom (rowHeight - textContentHeight + cellPaddingV).
30753096 // Image-only cells are excluded so they don't mask a tight text fit.
30763097 var naturalGap = lastRowHeight - maxTextContentH + cellPaddingV ;
3077- var postTableGap = Math . Max ( 2f , options . FontSize - naturalGap ) ;
3098+ // The next paragraph draws text at the baseline (state.CurrentY) and
3099+ // the visual top extends upward by ~fontSize*0.6 (font ascent). Use
3100+ // fontSize*0.8 as the floor so the text visual top clears the table
3101+ // bottom border with a small gap (~2 pt), matching Word behaviour.
3102+ var postTableGap = Math . Max ( options . FontSize * 0.8f , options . FontSize - naturalGap ) ;
30783103 state . AdvanceY ( postTableGap ) ;
30793104 }
30803105 else
@@ -3585,7 +3610,10 @@ private static float EstimateWrapTextWidth(string text, float fontSize, bool bol
35853610 var w = GetHelveticaCharWidth ( ch ) ;
35863611 var actual = ( hasCjk && ch == ' ' ) ? 500 : w ;
35873612 totalUnits += actual ;
3588- if ( ! ( w == 1000 && ch >= '\u2E80 ' ) )
3613+ // Exclude CJK fullwidth glyphs and auto-inserted thin spaces (\u2009)
3614+ // from the Latin fraction. Thin spaces are inter-script spacing that
3615+ // doesn't shrink under CJK font Latin-glyph reduction.
3616+ if ( ! ( w == 1000 && ch >= '\u2E80 ' ) && ch != '\u2009 ' )
35893617 latinUnits += actual ;
35903618 }
35913619 if ( latinUnits > 0 && totalUnits > 0 )
0 commit comments