1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-10-05 00:21:15 +03:00

Add a basic shrink to fit for tables

This commit is contained in:
Guillaume Ayoub 2012-03-23 19:31:54 +01:00
parent 82db8a421c
commit 42e25e1e3c
7 changed files with 100 additions and 22 deletions

View File

@ -638,6 +638,14 @@ def quotes(values):
return strings[::2], strings[1::2]
@validator()
@single_keyword
def table_layout(keyword):
"""Validation for the ``table-layout`` property"""
if keyword in ('fixed', 'auto'):
return keyword
@validator()
@single_keyword
def text_align(keyword):

View File

@ -14,7 +14,7 @@ from __future__ import division, unicode_literals
from .inlines import iter_line_boxes, replaced_box_width, replaced_box_height
from .markers import list_marker_layout
from .tables import table_layout, fixed_table_layout
from .tables import table_layout, fixed_table_layout, auto_table_layout
from .percentages import resolve_percentages
from ..formatting_structure import boxes
@ -377,15 +377,21 @@ def block_table_wrapper(document, wrapper, max_position_y, skip_stack,
raise ValueError('Table wrapper without a table')
resolve_percentages(wrapper, containing_block)
resolve_percentages(table, containing_block)
# Count the wrapper margins in case of `width: auto`
table.margin_left = wrapper.margin_left
table.margin_right = wrapper.margin_right
block_level_width(table, containing_block)
if table.style.table_layout == 'fixed':
block_level_width(table, containing_block)
fixed_table_layout(table)
else:
auto_table_layout(table, containing_block)
# The table margins are on the table wrapper box, not on the table box
table.margin_left = 0
table.margin_right = 0
fixed_table_layout(table)
wrapper.width = wrapper.style.width = table.border_width()
return block_box_layout(document, wrapper, max_position_y, skip_stack,
containing_block, device_size, page_is_empty,

View File

@ -290,8 +290,7 @@ def inline_block_box_layout(document, box, position_x, skip_stack,
box.margin_right = 0
if box.width == 'auto':
preferred, minimum = shrink_to_fit(box)
box.width = min(max(minimum, containing_block.width), preferred)
box.width = shrink_to_fit(box, containing_block.width)
box.position_x = position_x
box.position_y = 0

View File

@ -49,9 +49,15 @@ def variable_and_fixed_widths(box, width=None):
return variable_ratio, fixed_width
def shrink_to_fit(box):
"""Return ``(preferred_width, preferred_mimimum_width)`` for ``box``."""
return preferred_width(box), preferred_mimimum_width(box)
def shrink_to_fit(box, available_width):
"""Return the shrink-to-fit width of ``box``.
http://www.w3.org/TR/CSS21/visudet.html#float-width
"""
return min(
max(preferred_mimimum_width(box), available_width),
preferred_width(box))
def preferred_mimimum_width(box):

View File

@ -16,6 +16,7 @@ from ..compat import xrange
from ..logger import LOGGER
from ..formatting_structure import boxes
from .percentages import resolve_percentages, resolve_one_percentage
from .preferred import preferred_mimimum_width, preferred_width
def table_layout(document, table, max_position_y, skip_stack,
@ -333,7 +334,57 @@ def fixed_table_layout(table):
# with possible floating point rounding errors.
# (unless there is zero column)
table.column_widths = column_widths
return column_widths
def auto_table_layout(table, containing_block):
"""Run the auto table layout and return a list of column widths.
http://www.w3.org/TR/CSS21/tables.html#auto-table-layout
"""
column_preferred_widths = []
column_preferred_minimum_widths = []
for i, row in enumerate(table.children):
# TODO: handle row groups
for j, row_group in enumerate(row.children):
for k, cell in enumerate(row_group.children):
assert k <= len(column_preferred_widths)
if k == len(column_preferred_widths):
column_preferred_widths.append([0] * i)
column_preferred_minimum_widths.append([0] * i)
column_preferred_widths[k].append(preferred_width(cell))
column_preferred_minimum_widths[k].append(
preferred_mimimum_width(cell))
column_preferred_widths = [
max(widths) for widths in column_preferred_widths]
column_preferred_minimum_widths = [
max(widths) for widths in column_preferred_minimum_widths]
table_preferred_minimum_width = sum(column_preferred_minimum_widths)
table_preferred_width = sum(column_preferred_widths)
table_maximum_width = max(
containing_block.width, table_preferred_minimum_width)
# TODO: handle the border spacings
table.width = min(table_preferred_width, table_maximum_width)
# TODO: find a better algorithm
if table_preferred_width == table.width:
# Preferred width fits in the containing block
table.column_widths = column_preferred_widths
else:
# Preferred width is too large for the containing block
# Use the minimum widths and add the lost space to the columns
# according to their preferred widths
table.column_widths = column_preferred_minimum_widths
lost_width = (
min(containing_block.width, table_preferred_width) -
table_preferred_minimum_width)
table.column_widths = [
(column_width + lost_width *
preferred_column_width / table_preferred_width)
for (preferred_column_width, column_width)
in zip(column_preferred_widths, column_preferred_minimum_widths)]
def cell_baseline(cell):

View File

@ -1049,7 +1049,7 @@ def test_tables():
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_,
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_,
], source % {'extra_css': '''
table { border-color: #00f }
table { border-color: #00f; table-layout: fixed }
td { border-color: rgba(255, 0, 0, 0.5) }
'''})
@ -1083,7 +1083,7 @@ def test_tables():
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_,
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_,
], source % {'extra_css': '''
table { border-color: #00f }
table { border-color: #00f; table-layout: fixed }
td { background: rgba(255, 0, 0, 0.5) }
'''})
@ -1120,7 +1120,7 @@ def test_tables():
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_,
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_,
], source % {'extra_css': '''
table { border-color: #00f }
table { border-color: #00f; table-layout: fixed }
colgroup { background: rgba(255, 0, 0, 0.5) }
col { background: rgba(0, 255, 0, 0.5) }
'''})
@ -1155,7 +1155,7 @@ def test_tables():
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_,
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_,
], source % {'extra_css': '''
table { border-color: #00f }
table { border-color: #00f; table-layout: fixed }
thead { background: rgba(255, 0, 0, 0.5) }
tr { background: rgba(0, 255, 0, 0.5) }
'''})

View File

@ -713,7 +713,8 @@ def test_table_page_breaks():
rows_per_page, rows_position_y = run('''
<style>
@page { -weasy-size: 120px }
h1 { height: 30px}
table { table-layout: fixed }
h1 { height: 30px }
td { height: 40px }
</style>
<h1>Dummy title</h1>
@ -739,7 +740,7 @@ def test_table_page_breaks():
@page { -weasy-size: 120px }
h1 { height: 30px}
td { height: 40px }
table { page-break-inside: avoid }
table { page-break-inside: avoid; table-layout: fixed }
</style>
<h1>Dummy title</h1>
<table>
@ -758,7 +759,7 @@ def test_table_page_breaks():
@page { -weasy-size: 120px }
h1 { height: 30px}
td { height: 40px }
table { page-break-inside: avoid }
table { page-break-inside: avoid; table-layout: fixed }
</style>
<h1>Dummy title</h1>
<table>
@ -779,6 +780,7 @@ def test_table_page_breaks():
@page { -weasy-size: 120px }
h1 { height: 30px}
td { height: 40px }
table { table-layout: fixed }
</style>
<h1>Dummy title</h1>
<table>
@ -1577,7 +1579,10 @@ def test_table_column_width():
source = '''
<style>
body { width: 20000px; margin: 0 }
table { width: 10000px; margin: 0 auto; border-spacing: 100px 0 }
table {
width: 10000px; margin: 0 auto; border-spacing: 100px 0;
table-layout: fixed
}
td { border: 10px solid; padding: 1px }
</style>
<table>
@ -1603,7 +1608,7 @@ def test_table_column_width():
page, = parse(source)
assert len(logs) == 1
assert logs[0] == ('WARNING: This table row has more columns than '
'the table, ignored 1 cells: (<TableCellBox td 22>,)')
'the table, ignored 1 cells: (<TableCellBox td 25>,)')
html, = page.children
body, = html.children
wrapper, = body.children
@ -1669,7 +1674,7 @@ def test_table_column_width():
page, = parse('''
<style>
table { width: 1000px; border-spacing: 100px }
table { width: 1000px; border-spacing: 100px; table-layout: fixed }
</style>
<table>
<tr>
@ -1697,7 +1702,10 @@ def test_table_column_width():
page, = parse('''
<style>
body { width: %(body_width)s }
table { width: %(table_width)s; border-spacing: 100px }
table {
width: %(table_width)s; border-spacing: 100px;
table-layout: fixed
}
td { width: %(td_width)s }
</style>
<table>
@ -1725,7 +1733,7 @@ def test_table_column_width():
def test_table_row_height():
page, = parse('''
<table style="width: 1000px; border-spacing: 0 100px;
font: 20px/1em serif; margin: 3px">
font: 20px/1em serif; margin: 3px; table-layout: fixed">
<tr>
<td rowspan=0 style="height: 420px; vertical-align: top">
<td>X<br>X<br>X
@ -1808,7 +1816,7 @@ def test_table_wrapper():
page, = parse('''
<style>
@page { -weasy-size: 1000px }
table { /* width: auto; */ height: 500px;
table { /* width: auto; */ height: 500px; table-layout: fixed;
padding: 1px; border: 10px solid; margin: 100px; }
</style>
<table></table>