feat: add comprehensive GitHub workflow and development tools
This commit is contained in:
156
app/.venv/Lib/site-packages/weasyprint/layout/percent.py
Normal file
156
app/.venv/Lib/site-packages/weasyprint/layout/percent.py
Normal file
@@ -0,0 +1,156 @@
|
||||
"""Resolve percentages into fixed values."""
|
||||
|
||||
from math import inf
|
||||
|
||||
from ..formatting_structure import boxes
|
||||
|
||||
|
||||
def percentage(value, refer_to):
|
||||
"""Return the percentage of the reference value, or the value unchanged.
|
||||
|
||||
``refer_to`` is the length for 100%. If ``refer_to`` is not a number, it
|
||||
just replaces percentages.
|
||||
|
||||
"""
|
||||
if value is None or value == 'auto':
|
||||
return value
|
||||
elif value.unit == 'px':
|
||||
return value.value
|
||||
else:
|
||||
assert value.unit == '%'
|
||||
return refer_to * value.value / 100
|
||||
|
||||
|
||||
def resolve_one_percentage(box, property_name, refer_to,
|
||||
main_flex_direction=None):
|
||||
"""Set a used length value from a computed length value.
|
||||
|
||||
``refer_to`` is the length for 100%. If ``refer_to`` is not a number, it
|
||||
just replaces percentages.
|
||||
|
||||
"""
|
||||
# box.style has computed values
|
||||
value = box.style[property_name]
|
||||
# box attributes are used values
|
||||
percent = percentage(value, refer_to)
|
||||
setattr(box, property_name, percent)
|
||||
if property_name in ('min_width', 'min_height') and percent == 'auto':
|
||||
if (main_flex_direction is None or
|
||||
property_name != (f'min_{main_flex_direction}')):
|
||||
setattr(box, property_name, 0)
|
||||
|
||||
|
||||
def resolve_position_percentages(box, containing_block):
|
||||
cb_width, cb_height = containing_block
|
||||
resolve_one_percentage(box, 'left', cb_width)
|
||||
resolve_one_percentage(box, 'right', cb_width)
|
||||
resolve_one_percentage(box, 'top', cb_height)
|
||||
resolve_one_percentage(box, 'bottom', cb_height)
|
||||
|
||||
|
||||
def resolve_percentages(box, containing_block, main_flex_direction=None):
|
||||
"""Set used values as attributes of the box object."""
|
||||
if isinstance(containing_block, boxes.Box):
|
||||
# cb is short for containing block
|
||||
cb_width = containing_block.width
|
||||
cb_height = containing_block.height
|
||||
else:
|
||||
cb_width, cb_height = containing_block
|
||||
if isinstance(box, boxes.PageBox):
|
||||
maybe_height = cb_height
|
||||
else:
|
||||
maybe_height = cb_width
|
||||
resolve_one_percentage(box, 'margin_left', cb_width)
|
||||
resolve_one_percentage(box, 'margin_right', cb_width)
|
||||
resolve_one_percentage(box, 'margin_top', maybe_height)
|
||||
resolve_one_percentage(box, 'margin_bottom', maybe_height)
|
||||
resolve_one_percentage(box, 'padding_left', cb_width)
|
||||
resolve_one_percentage(box, 'padding_right', cb_width)
|
||||
resolve_one_percentage(box, 'padding_top', maybe_height)
|
||||
resolve_one_percentage(box, 'padding_bottom', maybe_height)
|
||||
resolve_one_percentage(box, 'width', cb_width)
|
||||
resolve_one_percentage(box, 'min_width', cb_width, main_flex_direction)
|
||||
resolve_one_percentage(box, 'max_width', cb_width, main_flex_direction)
|
||||
|
||||
# XXX later: top, bottom, left and right on positioned elements
|
||||
|
||||
if cb_height == 'auto':
|
||||
# Special handling when the height of the containing block
|
||||
# depends on its content.
|
||||
height = box.style['height']
|
||||
if height == 'auto' or height.unit == '%':
|
||||
box.height = 'auto'
|
||||
else:
|
||||
assert height.unit == 'px'
|
||||
box.height = height.value
|
||||
resolve_one_percentage(box, 'min_height', 0, main_flex_direction)
|
||||
resolve_one_percentage(box, 'max_height', inf, main_flex_direction)
|
||||
else:
|
||||
resolve_one_percentage(box, 'height', cb_height)
|
||||
resolve_one_percentage(
|
||||
box, 'min_height', cb_height, main_flex_direction)
|
||||
resolve_one_percentage(
|
||||
box, 'max_height', cb_height, main_flex_direction)
|
||||
|
||||
collapse = box.style['border_collapse'] == 'collapse'
|
||||
# Used value == computed value
|
||||
for side in ('top', 'right', 'bottom', 'left'):
|
||||
prop = f'border_{side}_width'
|
||||
# border-{side}-width would have been resolved
|
||||
# during border conflict resolution for collapsed-borders
|
||||
if not (collapse and hasattr(box, prop)):
|
||||
setattr(box, prop, box.style[prop])
|
||||
|
||||
# Shrink *content* widths and heights according to box-sizing
|
||||
# Thanks heavens and the spec: Our validator rejects negative values
|
||||
# for padding and border-width
|
||||
if box.style['box_sizing'] == 'border-box':
|
||||
horizontal_delta = (
|
||||
box.padding_left + box.padding_right +
|
||||
box.border_left_width + box.border_right_width)
|
||||
vertical_delta = (
|
||||
box.padding_top + box.padding_bottom +
|
||||
box.border_top_width + box.border_bottom_width)
|
||||
elif box.style['box_sizing'] == 'padding-box':
|
||||
horizontal_delta = box.padding_left + box.padding_right
|
||||
vertical_delta = box.padding_top + box.padding_bottom
|
||||
else:
|
||||
assert box.style['box_sizing'] == 'content-box'
|
||||
horizontal_delta = 0
|
||||
vertical_delta = 0
|
||||
|
||||
# Keep at least min_* >= 0 to prevent funny output in case box.width or
|
||||
# box.height become negative.
|
||||
# Restricting max_* seems reasonable, too.
|
||||
if horizontal_delta > 0:
|
||||
if box.width != 'auto':
|
||||
box.width = max(0, box.width - horizontal_delta)
|
||||
box.max_width = max(0, box.max_width - horizontal_delta)
|
||||
if box.min_width != 'auto':
|
||||
box.min_width = max(0, box.min_width - horizontal_delta)
|
||||
if vertical_delta > 0:
|
||||
if box.height != 'auto':
|
||||
box.height = max(0, box.height - vertical_delta)
|
||||
box.max_height = max(0, box.max_height - vertical_delta)
|
||||
if box.min_height != 'auto':
|
||||
box.min_height = max(0, box.min_height - vertical_delta)
|
||||
|
||||
|
||||
def resolve_radii_percentages(box):
|
||||
for corner in ('top_left', 'top_right', 'bottom_right', 'bottom_left'):
|
||||
property_name = f'border_{corner}_radius'
|
||||
rx, ry = box.style[property_name]
|
||||
|
||||
# Short track for common case
|
||||
if (0, 'px') in (rx, ry):
|
||||
setattr(box, property_name, (0, 0))
|
||||
continue
|
||||
|
||||
for side in corner.split('_'):
|
||||
if side in box.remove_decoration_sides:
|
||||
setattr(box, property_name, (0, 0))
|
||||
break
|
||||
else:
|
||||
rx = percentage(rx, box.border_width())
|
||||
ry = percentage(ry, box.border_height())
|
||||
setattr(box, property_name, (rx, ry))
|
||||
Reference in New Issue
Block a user