mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-10-04 16:07:57 +03:00
Merge branch 'master' into perf
This commit is contained in:
commit
ba2b4542e8
@ -15,6 +15,7 @@ import shutil
|
||||
import warnings
|
||||
|
||||
import cairocffi as cairo
|
||||
from weasyprint.layout import LayoutContext
|
||||
|
||||
from . import CSS
|
||||
from .css import get_all_computed_styles
|
||||
@ -347,9 +348,10 @@ class Document(object):
|
||||
<weasyprint.fonts.FontConfiguration>`.
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _render(cls, html, stylesheets, enable_hinting,
|
||||
presentational_hints=False, font_config=None):
|
||||
def _build_layout_context(cls, html, stylesheets, enable_hinting,
|
||||
presentational_hints=False, font_config=None):
|
||||
if font_config is None:
|
||||
font_config = FontConfiguration()
|
||||
target_collector = TargetCollector()
|
||||
@ -367,12 +369,26 @@ class Document(object):
|
||||
get_image_from_uri = functools.partial(
|
||||
original_get_image_from_uri, {}, html.url_fetcher)
|
||||
PROGRESS_LOGGER.info('Step 4 - Creating formatting structure')
|
||||
context = LayoutContext(
|
||||
enable_hinting, style_for, get_image_from_uri, font_config,
|
||||
target_collector)
|
||||
return context
|
||||
|
||||
@classmethod
|
||||
def _render(cls, html, stylesheets, enable_hinting,
|
||||
presentational_hints=False, font_config=None):
|
||||
if font_config is None:
|
||||
font_config = FontConfiguration()
|
||||
|
||||
context = cls._build_layout_context(
|
||||
html, stylesheets, enable_hinting, presentational_hints,
|
||||
font_config)
|
||||
|
||||
root_box = build_formatting_structure(
|
||||
html.etree_element, style_for, get_image_from_uri,
|
||||
html.base_url, target_collector)
|
||||
page_boxes = layout_document(
|
||||
enable_hinting, style_for, get_image_from_uri, root_box,
|
||||
font_config, html, target_collector)
|
||||
html.etree_element, context.style_for, context.get_image_from_uri,
|
||||
html.base_url, context.target_collector)
|
||||
|
||||
page_boxes = layout_document(html, root_box, context)
|
||||
rendering = cls(
|
||||
[Page(page_box, enable_hinting) for page_box in page_boxes],
|
||||
DocumentMetadata(**html._get_metadata()),
|
||||
|
@ -101,8 +101,7 @@ def layout_fixed_boxes(context, pages, containing_page):
|
||||
absolute_boxes = new_absolute_boxes
|
||||
|
||||
|
||||
def layout_document(enable_hinting, style_for, get_image_from_uri, root_box,
|
||||
font_config, html, target_collector, max_loops=8):
|
||||
def layout_document(html, root_box, context, max_loops=8):
|
||||
"""Lay out the whole document.
|
||||
|
||||
This includes line breaks, page breaks, absolute size and position for all
|
||||
@ -114,9 +113,6 @@ def layout_document(enable_hinting, style_for, get_image_from_uri, root_box,
|
||||
:returns: a list of laid out Page objects.
|
||||
|
||||
"""
|
||||
context = LayoutContext(
|
||||
enable_hinting, style_for, get_image_from_uri, font_config,
|
||||
target_collector)
|
||||
initialize_page_maker(context, root_box)
|
||||
pages = []
|
||||
actual_total_pages = 0
|
||||
@ -127,7 +123,7 @@ def layout_document(enable_hinting, style_for, get_image_from_uri, root_box,
|
||||
'Step 5 - Creating layout - Repagination #%i' % loop)
|
||||
|
||||
initial_total_pages = actual_total_pages
|
||||
pages = list(make_all_pages(context, root_box, html, pages, style_for))
|
||||
pages = list(make_all_pages(context, root_box, html, pages))
|
||||
actual_total_pages = len(pages)
|
||||
|
||||
# Check whether another round is required
|
||||
@ -185,7 +181,7 @@ def layout_document(enable_hinting, style_for, get_image_from_uri, root_box,
|
||||
state = context.page_maker[context.current_page][3]
|
||||
page.children = (root,) + tuple(
|
||||
make_margin_boxes(context, page, state))
|
||||
layout_backgrounds(page, get_image_from_uri)
|
||||
layout_backgrounds(page, context.get_image_from_uri)
|
||||
yield page
|
||||
|
||||
|
||||
|
@ -693,7 +693,7 @@ def set_page_type_computed_styles(page_type, html, style_for):
|
||||
base_url=html.base_url)
|
||||
|
||||
|
||||
def remake_page(index, context, root_box, html, style_for):
|
||||
def remake_page(index, context, root_box, html):
|
||||
"""Return one laid out page without margin boxes.
|
||||
|
||||
Start with the initial values from ``context.page_maker[index]``.
|
||||
@ -729,7 +729,7 @@ def remake_page(index, context, root_box, html, style_for):
|
||||
next_page_name = ''
|
||||
side = 'right' if right_page else 'left'
|
||||
page_type = PageType(side, blank, first, index, name=next_page_name)
|
||||
set_page_type_computed_styles(page_type, html, style_for)
|
||||
set_page_type_computed_styles(page_type, html, context.style_for)
|
||||
|
||||
context.forced_break = (
|
||||
initial_next_page['break'] != 'any' or initial_next_page['page'])
|
||||
@ -782,7 +782,7 @@ def remake_page(index, context, root_box, html, style_for):
|
||||
return page, resume_at
|
||||
|
||||
|
||||
def make_all_pages(context, root_box, html, pages, style_for):
|
||||
def make_all_pages(context, root_box, html, pages):
|
||||
"""Return a list of laid out pages without margin boxes.
|
||||
|
||||
Re-make pages only if necessary.
|
||||
@ -800,8 +800,7 @@ def make_all_pages(context, root_box, html, pages, style_for):
|
||||
remake_state['pages_wanted'] = False
|
||||
remake_state['anchors'] = []
|
||||
remake_state['content_lookups'] = []
|
||||
page, resume_at = remake_page(
|
||||
i, context, root_box, html, style_for)
|
||||
page, resume_at = remake_page(i, context, root_box, html)
|
||||
yield page
|
||||
else:
|
||||
PROGRESS_LOGGER.info(
|
||||
|
@ -42,12 +42,13 @@ def min_content_width(context, box, outer=True):
|
||||
This is the width by breaking at every line-break opportunity.
|
||||
|
||||
"""
|
||||
if isinstance(box, (
|
||||
if box.is_table_wrapper:
|
||||
return table_and_columns_preferred_widths(context, box, outer)[0]
|
||||
elif isinstance(box, boxes.TableCellBox):
|
||||
return table_cell_min_content_width(context, box, outer)
|
||||
elif isinstance(box, (
|
||||
boxes.BlockContainerBox, boxes.TableColumnBox, boxes.FlexBox)):
|
||||
if box.is_table_wrapper:
|
||||
return table_and_columns_preferred_widths(context, box, outer)[0]
|
||||
else:
|
||||
return block_min_content_width(context, box, outer)
|
||||
return block_min_content_width(context, box, outer)
|
||||
elif isinstance(box, boxes.TableColumnGroupBox):
|
||||
return column_group_content_width(context, box)
|
||||
elif isinstance(box, (boxes.InlineBox, boxes.LineBox)):
|
||||
@ -69,12 +70,13 @@ def max_content_width(context, box, outer=True):
|
||||
This is the width by only breaking at forced line breaks.
|
||||
|
||||
"""
|
||||
if isinstance(box, (
|
||||
if box.is_table_wrapper:
|
||||
return table_and_columns_preferred_widths(context, box, outer)[1]
|
||||
elif isinstance(box, boxes.TableCellBox):
|
||||
return table_cell_max_content_width(context, box, outer)
|
||||
elif isinstance(box, (
|
||||
boxes.BlockContainerBox, boxes.TableColumnBox, boxes.FlexBox)):
|
||||
if box.is_table_wrapper:
|
||||
return table_and_columns_preferred_widths(context, box, outer)[1]
|
||||
else:
|
||||
return block_max_content_width(context, box, outer)
|
||||
return block_max_content_width(context, box, outer)
|
||||
elif isinstance(box, boxes.TableColumnGroupBox):
|
||||
return column_group_content_width(context, box)
|
||||
elif isinstance(box, (boxes.InlineBox, boxes.LineBox)):
|
||||
@ -206,7 +208,7 @@ def inline_max_content_width(context, box, outer=True, is_line_start=False):
|
||||
|
||||
|
||||
def column_group_content_width(context, box):
|
||||
"""Return the *-content width for an ``TableColumnGroupBox``."""
|
||||
"""Return the *-content width for a ``TableColumnGroupBox``."""
|
||||
width = box.style['width']
|
||||
if width == 'auto' or width.unit == '%':
|
||||
width = 0
|
||||
@ -217,6 +219,31 @@ def column_group_content_width(context, box):
|
||||
return adjust(box, False, width)
|
||||
|
||||
|
||||
def table_cell_min_content_width(context, box, outer):
|
||||
"""Return the min-content width for a ``TableCellBox``."""
|
||||
children_widths = [
|
||||
min_content_width(context, child, outer=True)
|
||||
for child in box.children
|
||||
if not child.is_absolutely_positioned()]
|
||||
children_min_width = margin_width(
|
||||
box, 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)
|
||||
|
||||
|
||||
def table_cell_max_content_width(context, box, outer):
|
||||
"""Return the max-content width for a ``TableCellBox``."""
|
||||
return max(
|
||||
table_cell_min_content_width(context, box, outer),
|
||||
block_max_content_width(context, box, outer))
|
||||
|
||||
|
||||
def inline_line_widths(context, box, outer, is_line_start, minimum,
|
||||
skip_stack=None, first_line=False):
|
||||
if box.style['text_indent'].unit == '%':
|
||||
|
@ -382,6 +382,35 @@ def test_layout_table_auto_4():
|
||||
assert table.width == 27 # 3 * spacing + 4 + 4 + 2 * b1 + 2 * b2
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_layout_table_auto_5():
|
||||
page, = render_pages('''
|
||||
<style>
|
||||
@font-face { src: url(AHEM____.TTF); font-family: ahem }
|
||||
* { font-family: ahem }
|
||||
</style>
|
||||
<table style="width: 1000px; font-family: ahem">
|
||||
<tr>
|
||||
<td style="width: 40px">aa aa aa aa</td>
|
||||
<td style="width: 40px">aaaaaaaaaaa</td>
|
||||
<td>This will take the rest of the width</td>
|
||||
</tr>
|
||||
</table>
|
||||
''')
|
||||
html, = page.children
|
||||
body, = html.children
|
||||
table_wrapper, = body.children
|
||||
table, = table_wrapper.children
|
||||
row_group, = table.children
|
||||
row, = row_group.children
|
||||
td_1, td_2, td_3 = row.children
|
||||
|
||||
assert table.width == 1000
|
||||
assert td_1.width == 40
|
||||
assert td_2.width == 11 * 16
|
||||
assert td_3.width == 1000 - 40 - 11 * 16
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_layout_table_auto_6():
|
||||
page, = render_pages('''
|
||||
|
Loading…
Reference in New Issue
Block a user