Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 'rem' support #295

Closed
wants to merge 12 commits into from
34 changes: 19 additions & 15 deletions weasyprint/css/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,27 +264,30 @@ def add_declaration(cascaded_styles, prop_name, prop_values, weight, element,
style[prop_name] = prop_values, weight


def set_computed_styles(cascaded_styles, computed_styles,
element, parent, pseudo_type=None):
def set_computed_styles(cascaded_styles, computed_styles, element, parent,
root=None, pseudo_type=None):
"""Set the computed values of styles to ``element``.

Take the properties left by ``apply_style_rule`` on an element or
pseudo-element and assign computed values with respect to the cascade,
declaration priority (ie. ``!important``) and selector specificity.

"""
if parent is None:
parent_style = None
else:
parent_style = computed_styles[parent, None]

parent_style = computed_styles[parent, None] \
if parent is not None else None
# When specified on the font-size property of the root element, the rem
# units refer to the property’s initial value.
root_style = {'font_size': properties.INITIAL_VALUES['font_size']} \
if element is root else computed_styles[root, None]
cascaded = cascaded_styles.get((element, pseudo_type), {})
style = computed_from_cascaded(
element, cascaded, parent_style, pseudo_type)
computed_styles[element, pseudo_type] = style

computed_styles[element, pseudo_type] = computed_from_cascaded(
element, cascaded, parent_style, pseudo_type, root_style
)


def computed_from_cascaded(element, cascaded, parent_style, pseudo_type=None):
def computed_from_cascaded(element, cascaded, parent_style, pseudo_type=None,
root_style=None):
"""Get a dict of computed style mixed from parent and cascaded styles."""
if not cascaded and parent_style is not None:
# Fast path for anonymous boxes:
Expand Down Expand Up @@ -330,7 +333,8 @@ def computed_from_cascaded(element, cascaded, parent_style, pseudo_type=None):
specified[name] = value

return computed_values.compute(
element, pseudo_type, specified, computed, parent_style)
element, pseudo_type, specified, computed, parent_style, root_style
)


class Selector(object):
Expand Down Expand Up @@ -501,7 +505,7 @@ def get_all_computed_styles(html, user_stylesheets=None):
# Iterate on all elements, even if there is no cascaded style for them.
for element in element_tree.iter():
set_computed_styles(cascaded_styles, computed_styles, element,
parent=element.getparent())
root=element_tree, parent=element.getparent())

# Then computed styles for @page.

Expand All @@ -512,7 +516,7 @@ def get_all_computed_styles(html, user_stylesheets=None):
cascaded_styles, computed_styles, page_type,
# @page inherits from the root element:
# http://lists.w3.org/Archives/Public/www-style/2012Jan/1164.html
parent=element_tree)
root=element_tree, parent=element_tree)

# Then computed styles for pseudo elements, in any order.
# Pseudo-elements inherit from their associated element so they come
Expand All @@ -527,7 +531,7 @@ def get_all_computed_styles(html, user_stylesheets=None):
set_computed_styles(cascaded_styles, computed_styles,
element, pseudo_type=pseudo_type,
# The pseudo-element inherits from the element.
parent=element)
root=element_tree, parent=element)

# This is mostly useful to make pseudo_type optional.
def style_for(element, pseudo_type=None, __get=computed_styles.get):
Expand Down
8 changes: 6 additions & 2 deletions weasyprint/css/computed_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ def decorator(function):
return decorator


def compute(element, pseudo_type, specified, computed, parent_style):
def compute(element, pseudo_type, specified, computed, parent_style,
root_style):
"""
Return a StyleDict of computed values.

Expand All @@ -184,6 +185,7 @@ def computer():
computer.specified = specified
computer.computed = computed
computer.parent_style = parent_style
computer.root_style = root_style

getter = COMPUTER_FUNCTIONS.get

Expand Down Expand Up @@ -282,7 +284,7 @@ def length(computer, name, value, font_size=None, pixels_only=False):
elif unit in LENGTHS_TO_PIXELS:
# Convert absolute lengths to pixels
result = value.value * LENGTHS_TO_PIXELS[unit]
elif unit in ('em', 'ex', 'ch'):
elif unit in ('em', 'ex', 'ch', 'rem'):
if font_size is None:
font_size = computer.computed.font_size
if unit == 'ex':
Expand All @@ -299,6 +301,8 @@ def length(computer, name, value, font_size=None, pixels_only=False):
result = value.value * logical_width
elif unit == 'em':
result = value.value * font_size
elif unit == 'rem':
result = value.value * computer.root_style.font_size
else:
# A percentage or 'auto': no conversion needed.
return value
Expand Down
3 changes: 2 additions & 1 deletion weasyprint/css/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@


# get the sets of keys
LENGTH_UNITS = set(computed_values.LENGTHS_TO_PIXELS) | set(['ex', 'em', 'ch'])
LENGTH_UNITS = set(computed_values.LENGTHS_TO_PIXELS) | \
set(['ex', 'em', 'ch', 'rem'])


# keyword -> (open, insert)
Expand Down