Skip to content
Permalink
Browse files

Support larger and smaller values for font-size

  • Loading branch information
liZe committed Sep 20, 2019
1 parent a0ccc8d commit 7a4d6f821d4560877060187d8d905fc2d57c904c
Showing with 59 additions and 8 deletions.
  1. +20 −5 weasyprint/css/computed_values.py
  2. +1 −2 weasyprint/css/validation/properties.py
  3. +38 −1 weasyprint/tests/test_css.py
@@ -10,6 +10,7 @@
"""

from collections import OrderedDict
from urllib.parse import unquote

from tinycss2.color3 import parse_color
@@ -28,8 +29,7 @@
# Value in pixels of font-size for <absolute-size> keywords: 12pt (16px) for
# medium, and scaling factors given in CSS3 for others:
# http://www.w3.org/TR/css3-fonts/#font-size-prop
# TODO: this will need to be ordered to implement 'smaller' and 'larger'
FONT_SIZE_KEYWORDS = dict(
FONT_SIZE_KEYWORDS = OrderedDict(
# medium is 16px, others are a ratio of medium
(name, INITIAL_VALUES['font_size'] * a / b)
for name, a, b in (
@@ -592,14 +592,29 @@ def font_size(computer, name, value):
"""Compute the ``font-size`` property."""
if value in FONT_SIZE_KEYWORDS:
return FONT_SIZE_KEYWORDS[value]
# TODO: support 'larger' and 'smaller'

keyword_values = list(FONT_SIZE_KEYWORDS.values())
parent_font_size = computer['parent_style']['font_size']

if value == 'larger':
if parent_font_size >= keyword_values[-1]:
return parent_font_size * 1.2
for i, keyword_value in enumerate(keyword_values):
if keyword_value > parent_font_size:
return keyword_values[i]
elif value == 'smaller':
if parent_font_size <= keyword_values[0]:
return parent_font_size * 0.8
for i, keyword_value in enumerate(keyword_values[::-1]):
if keyword_value < parent_font_size:
return keyword_values[-i - 1]

if value.unit == '%':
return value.value * parent_font_size / 100.
else:
return length(computer, name, value, pixels_only=True,
font_size=parent_font_size)
return length(
computer, name, value, pixels_only=True,
font_size=parent_font_size)


@register_computer('font-weight')
@@ -784,9 +784,8 @@ def font_size(token):
return length
font_size_keyword = get_keyword(token)
if font_size_keyword in ('smaller', 'larger'):
raise InvalidValues('value not supported yet')
return font_size_keyword
if font_size_keyword in computed_values.FONT_SIZE_KEYWORDS:
# or keyword in ('smaller', 'larger')
return font_size_keyword


@@ -9,6 +9,8 @@
"""

from math import isclose

import pytest
import tinycss2

@@ -83,7 +85,7 @@ def test_annotate_document():
style_for = get_all_computed_styles(
document, user_stylesheets=[CSS(resource_filename('user.css'))])

# Element objects behave a lists of their children
# Element objects behave as lists of their children
_head, body = document.etree_element
h1, p, ul, div = body
li_0, _li_1 = ul
@@ -451,3 +453,38 @@ def test_units(value, width):
body, = html.children
p, = body.children
assert p.margin_left == width


@assert_no_logs
@pytest.mark.parametrize('parent_css, parent_size, child_css, child_size', (
('10px', 10, '10px', 10),
('x-small', 12, 'xx-large', 32),
('x-large', 24, '2em', 48),
('1em', 16, '1em', 16),
('1em', 16, 'larger', 6 / 5 * 16),
('medium', 16, 'larger', 6 / 5 * 16),
('x-large', 24, 'larger', 32),
('xx-large', 32, 'larger', 1.2 * 32),
('1px', 1, 'larger', 3 / 5 * 16),
('28px', 28, 'larger', 32),
('100px', 100, 'larger', 120),
('xx-small', 3 / 5 * 16, 'larger', 12),
('1em', 16, 'smaller', 8 / 9 * 16),
('medium', 16, 'smaller', 8 / 9 * 16),
('x-large', 24, 'smaller', 6 / 5 * 16),
('xx-large', 32, 'smaller', 24),
('xx-small', 3 / 5 * 16, 'smaller', 0.8 * 3 / 5 * 16),
('1px', 1, 'smaller', 0.8),
('28px', 28, 'smaller', 24),
('100px', 100, 'smaller', 32),
))
def test_font_size(parent_css, parent_size, child_css, child_size):
document = FakeHTML(string='<p>a<span>b')
style_for = get_all_computed_styles(document, user_stylesheets=[CSS(
string='p{font-size:%s}span{font-size:%s}' % (parent_css, child_css))])

_head, body = document.etree_element
p, = body
span, = p
assert isclose(style_for(p)['font_size'], parent_size)
assert isclose(style_for(span)['font_size'], child_size)

0 comments on commit 7a4d6f8

Please sign in to comment.
You can’t perform that action at this time.