Repository: Kozea/WeasyPrint (python)

Issue:
Table not printed as shown in browser: weasyprint overrides "table width" with "cell width"
If the table (table) has a maximum width and the individual columns (td) have their own width - greater than the table width(!) - weasyprint interprets the width different as browsers will do:

A Table with "table width 500px" and "td width 3000px" will shown as follows:

- Browsers take the table-width as the relevant width -> Table will be 500px wide
- Weasyprint takes the td-width as relevant width -> Table will be 3000px wide (table will be cut off!)

![table-bug](https://github.com/Kozea/WeasyPrint/assets/5119643/1b2040bf-02ea-4a09-937d-6adc3a4601f9)

### Example code

```html
<!DOCTYPE html><html class="view  chrome"  lang="de">
<p> Table Width: 500px </p>
<div>    
<div style="overflow:auto">      
<div class="text-content">            
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">					
<tbody>			
<tr>				
<td style="width:3000px">Width: 3000px</td>				
<td style="width:609px">2</td>			
</tr>			
<tr>				
<td style="width:927px">Width: 927px</td>				
<td style="width:609px">2</td>			
</tr>			
<tr>				
<td style="width:927px">Width: 927px</td>				
<td style="width:609px">2</td>			
</tr>		
</tbody>	     
</table><p>&nbsp;</p>              	
</div>    
</div>  
</div>
</html> 
``` 


Pull request description:
Use CSS Table Module Level 3 to compute widths
CSS Table Module Level 3 appears to respect table width over cell width. Thus, the following ~3~ [`test_layout_table_auto_9`](https://github.com/Kozea/WeasyPrint/blob/e73526eda54d5a3e21037f05152aa1759938d3c6/tests/layout/test_table.py#L515-L547) and [`test_layout_table_auto_32`](https://github.com/Kozea/WeasyPrint/blob/e73526eda54d5a3e21037f05152aa1759938d3c6/tests/layout/test_table.py#L1112-L1123) tests which increase table widths fail:

```
==================================================================== short test summary info =====================================================================
FAILED tests/layout/test_table.py::test_layout_table_auto_9 - assert 53.33333333333333 == 60
FAILED tests/layout/test_table.py::test_layout_table_auto_10 - assert 6.666666666666666 == 6
FAILED tests/layout/test_table.py::test_layout_table_auto_32 - assert 500.0 == 600
===================================================== 3 failed, 2189 passed, 39 xfailed in 323.50s (0:05:23) =====================================================
```

This appear to be able to fix #1956

Patch:
diff --git a/weasyprint/layout/preferred.py b/weasyprint/layout/preferred.py
index 8c965fe7..10ddc6e3 100644
--- a/weasyprint/layout/preferred.py
+++ b/weasyprint/layout/preferred.py
@@ -256,13 +256,7 @@ def table_cell_min_content_width(context, box, outer):
         outer,
         max(children_widths) if children_widths else 0)
 
-    width = box.style['width']
-    if width != 'auto' and width.unit == 'px':
-        cell_min_width = adjust(box, outer, width.value)
-    else:
-        cell_min_width = 0
-
-    return max(children_min_width, cell_min_width)
+    return children_min_width
 
 
 def table_cell_max_content_width(context, box, outer):
diff --git a/weasyprint/layout/table.py b/weasyprint/layout/table.py
index dec83d18..fb490d6b 100644
--- a/weasyprint/layout/table.py
+++ b/weasyprint/layout/table.py
@@ -753,6 +753,7 @@ def auto_table_layout(context, box, containing_block):
     guesses = (
         min_content_guess, min_content_percentage_guess,
         min_content_specified_guess, max_content_guess)
+    # https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm
     for i in range(len(grid)):
         if column_intrinsic_percentages[i]:
             min_content_percentage_guess[i] = max(
@@ -761,7 +762,9 @@ def auto_table_layout(context, box, containing_block):
             min_content_specified_guess[i] = min_content_percentage_guess[i]
             max_content_guess[i] = min_content_percentage_guess[i]
         elif constrainedness[i]:
-            min_content_specified_guess[i] = column_min_content_widths[i]
+            # any other column that is constrained is assigned
+            # its max-content width
+            min_content_specified_guess[i] = column_max_content_widths[i]
 
     if assignable_width <= sum(max_content_guess):
         # Default values shouldn't be used, but we never know.


Test patch:
diff --git a/tests/layout/test_table.py b/tests/layout/test_table.py
index bfd097da..afcde2ba 100644
--- a/tests/layout/test_table.py
+++ b/tests/layout/test_table.py
@@ -515,7 +515,7 @@ def test_layout_table_auto_8():
 @assert_no_logs
 def test_layout_table_auto_9():
     page, = render_pages('''
-      <table style="border-spacing: 10px; width: 110px; margin: 5px">
+      <table style="border-spacing: 10px; width: 120px; margin: 5px">
         <tr>
           <td style="width: 60px"></td>
           <td></td>
@@ -1113,8 +1113,8 @@ def test_layout_table_auto_31():
 def test_layout_table_auto_32():
     # Table with a cell larger than the table's width
     page, = render_pages('''
-      <table style="width: 300px; margin: 100px">
-        <td style="width: 400px"></td>
+      <table style="width: 400px; margin: 100px">
+        <td style="width: 500px"></td>
       </table>
     ''')
     html, = page.children