diff --git a/weasy/css/computed_values.py b/weasy/css/computed_values.py index 67698086..7c8cdb79 100644 --- a/weasy/css/computed_values.py +++ b/weasy/css/computed_values.py @@ -549,6 +549,12 @@ def text_align(computer, name, value): @Computer.register('vertical_align') def vertical_align(computer, name, value): """Compute the ``word-spacing`` property.""" + # Use +/- half an em for super and sub, same as Pango. + # (See the SUPERSUB_RISE constant in pango-markup.c) + if value == 'super': + return computer.get_computed('font_size') * 0.5 + if value == 'sub': + return computer.get_computed('font_size') * -0.5 if getattr(value, 'type', 'other') == 'PERCENTAGE': return computer.get_computed('line_height') * value.value / 100. return length(computer, name, value) diff --git a/weasy/css/validation.py b/weasy/css/validation.py index fa71e4ef..11db2665 100644 --- a/weasy/css/validation.py +++ b/weasy/css/validation.py @@ -449,9 +449,10 @@ def vertical_align(value): if is_dimension_or_percentage(value, negative=True): return value keyword = get_keyword(value) - if keyword in ('sub', 'sup', 'text-top', 'text-bottom', 'top', 'bottom'): + if keyword in ('top', 'bottom'): raise InvalidValues('value not supported yet') - if keyword in ('baseline', 'middle'): + if keyword in ('baseline', 'middle', 'sub', 'super', + 'text-top', 'text-bottom'): return keyword diff --git a/weasy/layout/inlines.py b/weasy/layout/inlines.py index a5ce5f16..6bc95d36 100644 --- a/weasy/layout/inlines.py +++ b/weasy/layout/inlines.py @@ -489,6 +489,16 @@ def inline_box_verticality(box, baseline_y): one_ex = box.style.font_size * 0.5 top = baseline_y - (one_ex + child.margin_height()) / 2. child_baseline_y = top + child.baseline + elif vertical_align == 'text-top': + # align top with the top of the parent’s content area + top = (baseline_y - box.baseline + box.margin_top + + box.border_top_width + box.padding_top) + child_baseline_y = top + child.baseline + elif vertical_align == 'text-bottom': + # align bottom with the bottom of the parent’s content area + bottom = (baseline_y - box.baseline + box.margin_top + + box.border_top_width + box.padding_top + box.height) + child_baseline_y = bottom - child.margin_height() + child.baseline else: # Numeric value: The child’s baseline is `vertical_align` above # (lower y) the parent’s baseline. diff --git a/weasy/tests/test_layout.py b/weasy/tests/test_layout.py index 349c4afc..fe669d99 100644 --- a/weasy/tests/test_layout.py +++ b/weasy/tests/test_layout.py @@ -888,6 +888,47 @@ def test_vertical_align(): assert line.height == 77 assert body.height == line.height + # sup and sub currently mean +/- 0.5 em + # With the initial 16px font-size, that’s 8px. + page, = parse(''' + + + + + + ''') + html = page.root_box + body, = html.children + line, = body.children + span, = line.children + img_1, img_2, img_3 = span.children + assert img_1.height == 60 + assert img_2.height == 40 + assert img_3.height == 40 + assert img_1.position_y == 0 + assert img_2.position_y == 12 # 20 - 16 * 0.5 + assert img_3.position_y == 28 # 20 + 16 * 0.5 + assert line.height == 68 + assert body.height == line.height + + # Pango gives a height of 19px for font-size of 16px + page, = parse(''' + + + + + ''') + html = page.root_box + body, = html.children + line, = body.children + span, = line.children + img_1, img_2 = span.children + assert img_1.height == 4 + assert img_2.height == 4 + assert img_1.position_y == 0 + assert img_2.position_y == 15 # 19 - 4 + assert line.height == 19 + assert body.height == line.height @SUITE.test