weasyprint 65.1__py3-none-any.whl → 67.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- weasyprint/__init__.py +17 -7
- weasyprint/__main__.py +21 -10
- weasyprint/anchors.py +4 -4
- weasyprint/css/__init__.py +732 -67
- weasyprint/css/computed_values.py +65 -170
- weasyprint/css/counters.py +1 -1
- weasyprint/css/functions.py +206 -0
- weasyprint/css/html5_ua.css +3 -7
- weasyprint/css/html5_ua_form.css +2 -2
- weasyprint/css/media_queries.py +3 -1
- weasyprint/css/properties.py +6 -2
- weasyprint/css/{utils.py → tokens.py} +306 -397
- weasyprint/css/units.py +91 -0
- weasyprint/css/validation/__init__.py +1 -1
- weasyprint/css/validation/descriptors.py +47 -19
- weasyprint/css/validation/expanders.py +7 -8
- weasyprint/css/validation/properties.py +341 -357
- weasyprint/document.py +20 -19
- weasyprint/draw/__init__.py +56 -63
- weasyprint/draw/border.py +121 -69
- weasyprint/draw/color.py +1 -1
- weasyprint/draw/text.py +60 -41
- weasyprint/formatting_structure/boxes.py +24 -5
- weasyprint/formatting_structure/build.py +33 -45
- weasyprint/images.py +76 -62
- weasyprint/layout/__init__.py +32 -26
- weasyprint/layout/absolute.py +7 -6
- weasyprint/layout/background.py +7 -7
- weasyprint/layout/block.py +195 -152
- weasyprint/layout/column.py +19 -24
- weasyprint/layout/flex.py +54 -26
- weasyprint/layout/float.py +12 -7
- weasyprint/layout/grid.py +284 -90
- weasyprint/layout/inline.py +121 -68
- weasyprint/layout/page.py +45 -12
- weasyprint/layout/percent.py +14 -10
- weasyprint/layout/preferred.py +105 -63
- weasyprint/layout/replaced.py +9 -6
- weasyprint/layout/table.py +16 -9
- weasyprint/pdf/__init__.py +58 -18
- weasyprint/pdf/anchors.py +3 -4
- weasyprint/pdf/fonts.py +126 -69
- weasyprint/pdf/metadata.py +36 -4
- weasyprint/pdf/pdfa.py +19 -3
- weasyprint/pdf/pdfua.py +7 -115
- weasyprint/pdf/pdfx.py +83 -0
- weasyprint/pdf/stream.py +57 -49
- weasyprint/pdf/tags.py +307 -0
- weasyprint/stacking.py +14 -15
- weasyprint/svg/__init__.py +59 -32
- weasyprint/svg/bounding_box.py +4 -2
- weasyprint/svg/defs.py +4 -9
- weasyprint/svg/images.py +11 -3
- weasyprint/svg/text.py +11 -2
- weasyprint/svg/utils.py +15 -8
- weasyprint/text/constants.py +1 -1
- weasyprint/text/ffi.py +4 -3
- weasyprint/text/fonts.py +13 -5
- weasyprint/text/line_break.py +146 -43
- weasyprint/urls.py +41 -13
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/METADATA +5 -6
- weasyprint-67.0.dist-info/RECORD +77 -0
- weasyprint/draw/stack.py +0 -13
- weasyprint-65.1.dist-info/RECORD +0 -74
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/WHEEL +0 -0
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/entry_points.txt +0 -0
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/licenses/LICENSE +0 -0
weasyprint/layout/__init__.py
CHANGED
|
@@ -229,24 +229,22 @@ class LayoutContext:
|
|
|
229
229
|
self.font_config = font_config
|
|
230
230
|
self.counter_style = counter_style
|
|
231
231
|
self.target_collector = target_collector
|
|
232
|
-
self.
|
|
232
|
+
self._excluded_shapes_root_boxes = []
|
|
233
|
+
self._excluded_shapes = {}
|
|
233
234
|
self.footnotes = []
|
|
234
235
|
self.page_footnotes = {}
|
|
235
236
|
self.current_page_footnotes = []
|
|
236
237
|
self.reported_footnotes = []
|
|
237
238
|
self.current_footnote_area = None # Not initialized yet
|
|
238
|
-
self.excluded_shapes = None # Not initialized yet
|
|
239
239
|
self.page_bottom = None
|
|
240
|
-
self.string_set = defaultdict(lambda: defaultdict(
|
|
241
|
-
self.running_elements = defaultdict(lambda: defaultdict(
|
|
240
|
+
self.string_set = defaultdict(lambda: defaultdict(list))
|
|
241
|
+
self.running_elements = defaultdict(lambda: defaultdict(list))
|
|
242
242
|
self.current_page = None
|
|
243
243
|
self.forced_break = False
|
|
244
244
|
self.broken_out_of_flow = {}
|
|
245
245
|
self.in_column = False
|
|
246
246
|
|
|
247
247
|
# Cache
|
|
248
|
-
self.strut_layouts = {}
|
|
249
|
-
self.font_features = {}
|
|
250
248
|
self.tables = {}
|
|
251
249
|
self.dictionaries = {}
|
|
252
250
|
|
|
@@ -259,34 +257,39 @@ class LayoutContext:
|
|
|
259
257
|
# The 1e-9 value comes from PEP 485.
|
|
260
258
|
return position_y > bottom * (1 + 1e-9)
|
|
261
259
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
self.
|
|
260
|
+
@property
|
|
261
|
+
def excluded_shapes(self):
|
|
262
|
+
return self._excluded_shapes[self._excluded_shapes_root_boxes[-1]]
|
|
265
263
|
|
|
266
|
-
|
|
264
|
+
@excluded_shapes.setter
|
|
265
|
+
def excluded_shapes(self, excluded_shapes):
|
|
266
|
+
self._excluded_shapes[self._excluded_shapes_root_boxes[-1]] = excluded_shapes
|
|
267
|
+
|
|
268
|
+
def create_block_formatting_context(self, root_box=None, new_list=None):
|
|
269
|
+
assert root_box not in self._excluded_shapes_root_boxes
|
|
270
|
+
self._excluded_shapes_root_boxes.append(root_box)
|
|
271
|
+
if root_box not in self._excluded_shapes:
|
|
272
|
+
self._excluded_shapes[root_box] = [] if new_list is None else new_list
|
|
273
|
+
|
|
274
|
+
def finish_block_formatting_context(self, root_box=None):
|
|
267
275
|
# See https://www.w3.org/TR/CSS2/visudet.html#root-height
|
|
268
|
-
if root_box.style['height'] == 'auto' and self.excluded_shapes:
|
|
276
|
+
if root_box and root_box.style['height'] == 'auto' and self.excluded_shapes:
|
|
269
277
|
box_bottom = root_box.content_box_y() + root_box.height
|
|
270
278
|
max_shape_bottom = max([
|
|
271
279
|
shape.position_y + shape.margin_height()
|
|
272
280
|
for shape in self.excluded_shapes] + [box_bottom])
|
|
273
281
|
root_box.height += max_shape_bottom - box_bottom
|
|
274
|
-
self.
|
|
275
|
-
if self._excluded_shapes_lists:
|
|
276
|
-
self.excluded_shapes = self._excluded_shapes_lists[-1]
|
|
277
|
-
else:
|
|
278
|
-
self.excluded_shapes = None
|
|
282
|
+
self._excluded_shapes.pop(self._excluded_shapes_root_boxes.pop())
|
|
279
283
|
|
|
280
|
-
def create_flex_formatting_context(self):
|
|
281
|
-
self.
|
|
282
|
-
self._excluded_shapes_lists.append(self.excluded_shapes)
|
|
284
|
+
def create_flex_formatting_context(self, root_box):
|
|
285
|
+
self.create_block_formatting_context(root_box, FakeList())
|
|
283
286
|
|
|
284
287
|
def finish_flex_formatting_context(self, root_box):
|
|
285
|
-
self.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
self.
|
|
288
|
+
self.finish_block_formatting_context(root_box)
|
|
289
|
+
|
|
290
|
+
def add_broken_out_of_flow(self, new_box, box, containing_block, resume_at):
|
|
291
|
+
self.broken_out_of_flow[new_box] = (
|
|
292
|
+
box, containing_block, self._excluded_shapes_root_boxes[-1], resume_at)
|
|
290
293
|
|
|
291
294
|
def get_string_set_for(self, page, name, keyword='first'):
|
|
292
295
|
"""Resolve value of string function."""
|
|
@@ -389,10 +392,13 @@ class LayoutContext:
|
|
|
389
392
|
if not self.in_column:
|
|
390
393
|
self.page_bottom -= footnote_area.margin_height()
|
|
391
394
|
last_child = footnote_area.children[-1]
|
|
392
|
-
|
|
393
|
-
last_child.position_y + last_child.margin_height()
|
|
395
|
+
last_child_bottom = (
|
|
396
|
+
last_child.position_y + last_child.margin_height() -
|
|
397
|
+
last_child.margin_bottom)
|
|
398
|
+
footnote_area_bottom = (
|
|
394
399
|
footnote_area.position_y + footnote_area.margin_height() -
|
|
395
400
|
footnote_area.margin_bottom)
|
|
401
|
+
overflow = last_child_bottom > footnote_area_bottom
|
|
396
402
|
return overflow
|
|
397
403
|
else:
|
|
398
404
|
self.current_footnote_area.height = 0
|
weasyprint/layout/absolute.py
CHANGED
|
@@ -67,7 +67,9 @@ def absolute_width(box, context, cb_x, cb_y, cb_width, cb_height):
|
|
|
67
67
|
available_width = cb_width - (
|
|
68
68
|
paddings_borders + box.margin_left + box.margin_right)
|
|
69
69
|
box.width = shrink_to_fit(context, box, available_width)
|
|
70
|
-
if
|
|
70
|
+
if box.is_outside_marker:
|
|
71
|
+
translate_box_width = ltr
|
|
72
|
+
elif not ltr:
|
|
71
73
|
translate_box_width = True
|
|
72
74
|
translate_x = default_translate_x + available_width
|
|
73
75
|
elif box.left != 'auto' and box.right != 'auto' and box.width != 'auto':
|
|
@@ -200,7 +202,8 @@ def absolute_block(context, box, containing_block, fixed_boxes, bottom_space,
|
|
|
200
202
|
new_box, resume_at, _, _, _, _ = block_container_layout(
|
|
201
203
|
context, box, bottom_space, skip_stack, page_is_empty=True,
|
|
202
204
|
absolute_boxes=absolute_boxes, fixed_boxes=fixed_boxes,
|
|
203
|
-
adjoining_margins=None,
|
|
205
|
+
adjoining_margins=None, first_letter_style=None, first_line_style=None,
|
|
206
|
+
discard=False, max_lines=None)
|
|
204
207
|
elif isinstance(box, (boxes.FlexContainerBox)):
|
|
205
208
|
new_box, resume_at, _, _, _ = flex_layout(
|
|
206
209
|
context, box, bottom_space, skip_stack, containing_block,
|
|
@@ -235,8 +238,7 @@ def absolute_layout(context, placeholder, containing_block, fixed_boxes,
|
|
|
235
238
|
context, box, containing_block, fixed_boxes, bottom_space, skip_stack)
|
|
236
239
|
placeholder.set_laid_out_box(new_box)
|
|
237
240
|
if resume_at:
|
|
238
|
-
context.
|
|
239
|
-
box, containing_block, resume_at)
|
|
241
|
+
context.add_broken_out_of_flow(placeholder, box, containing_block, resume_at)
|
|
240
242
|
|
|
241
243
|
|
|
242
244
|
def absolute_box_layout(context, box, containing_block, fixed_boxes,
|
|
@@ -257,7 +259,6 @@ def absolute_box_layout(context, box, containing_block, fixed_boxes,
|
|
|
257
259
|
resolve_percentages(box, (cb_width, cb_height))
|
|
258
260
|
resolve_position_percentages(box, (cb_width, cb_height))
|
|
259
261
|
|
|
260
|
-
context.create_block_formatting_context()
|
|
261
262
|
if isinstance(box, boxes.BlockReplacedBox):
|
|
262
263
|
new_box = absolute_replaced(
|
|
263
264
|
context, box, cb_x, cb_y, cb_width, cb_height)
|
|
@@ -267,7 +268,7 @@ def absolute_box_layout(context, box, containing_block, fixed_boxes,
|
|
|
267
268
|
new_box, resume_at = absolute_block(
|
|
268
269
|
context, box, containing_block, fixed_boxes, bottom_space,
|
|
269
270
|
skip_stack, cb_x, cb_y, cb_width, cb_height)
|
|
270
|
-
|
|
271
|
+
|
|
271
272
|
return new_box, resume_at
|
|
272
273
|
|
|
273
274
|
|
weasyprint/layout/background.py
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
from collections import namedtuple
|
|
4
4
|
from itertools import cycle
|
|
5
5
|
|
|
6
|
-
from tinycss2.
|
|
6
|
+
from tinycss2.color5 import parse_color
|
|
7
7
|
|
|
8
8
|
from ..formatting_structure import boxes
|
|
9
9
|
from . import replaced
|
|
10
10
|
from .percent import percentage, resolve_radii_percentages
|
|
11
11
|
|
|
12
|
-
Background = namedtuple('Background', 'color, layers,
|
|
12
|
+
Background = namedtuple('Background', 'color, layers, style')
|
|
13
13
|
BackgroundLayer = namedtuple(
|
|
14
14
|
'BackgroundLayer',
|
|
15
15
|
'image, size, position, repeat, unbounded, '
|
|
@@ -88,7 +88,7 @@ def layout_box_backgrounds(page, box, get_image_from_uri, layout_children=True,
|
|
|
88
88
|
style['background_origin'],
|
|
89
89
|
style['background_position'],
|
|
90
90
|
style['background_attachment']]))]
|
|
91
|
-
box.background = Background(color, layers, style
|
|
91
|
+
box.background = Background(color, layers, style)
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
def layout_background_layer(box, page, resolution, image, size, clip, repeat,
|
|
@@ -177,15 +177,15 @@ def layout_background_layer(box, page, resolution, image, size, clip, repeat,
|
|
|
177
177
|
size_width, size_height = size
|
|
178
178
|
image_width, image_height = replaced.default_image_sizing(
|
|
179
179
|
intrinsic_width, intrinsic_height, ratio,
|
|
180
|
-
percentage(size_width, positioning_width),
|
|
181
|
-
percentage(size_height, positioning_height),
|
|
180
|
+
percentage(size_width, box.style, positioning_width),
|
|
181
|
+
percentage(size_height, box.style, positioning_height),
|
|
182
182
|
positioning_width, positioning_height)
|
|
183
183
|
|
|
184
184
|
origin_x, position_x, origin_y, position_y = position
|
|
185
185
|
ref_x = positioning_width - image_width
|
|
186
186
|
ref_y = positioning_height - image_height
|
|
187
|
-
position_x = percentage(position_x, ref_x)
|
|
188
|
-
position_y = percentage(position_y, ref_y)
|
|
187
|
+
position_x = percentage(position_x, box.style, ref_x)
|
|
188
|
+
position_y = percentage(position_y, box.style, ref_y)
|
|
189
189
|
if origin_x == 'right':
|
|
190
190
|
position_x = ref_x - position_x
|
|
191
191
|
if origin_y == 'bottom':
|