diff --git a/.gitignore b/.gitignore index 679c13ea..676b4ba6 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,4 @@ # Tests /weasyprint/tests/.cache -/weasyprint/tests/results +/weasyprint/tests/test_draw/results diff --git a/weasyprint/tests/test_api.py b/weasyprint/tests/test_api.py index 13edf267..bdfd62c3 100644 --- a/weasyprint/tests/test_api.py +++ b/weasyprint/tests/test_api.py @@ -9,41 +9,27 @@ """ -import contextlib import gzip import io import math import os import sys -import threading import unicodedata import zlib from urllib.parse import urljoin, uses_relative import cairocffi as cairo +import py import pytest from pdfrw import PdfReader from .. import CSS, HTML, __main__, default_url_fetcher from ..urls import path2url -from .test_draw import B, _, assert_pixels_equal, image_to_pixels, r +from .test_draw import assert_pixels_equal, image_to_pixels +from .test_draw.test_draw import B, _, r from .testing_utils import ( FakeHTML, assert_no_logs, capture_logs, http_server, resource_filename) -CHDIR_LOCK = threading.Lock() - - -@contextlib.contextmanager -def chdir(path): - """Change the current directory in a context manager.""" - with CHDIR_LOCK: - old_dir = os.getcwd() - try: - os.chdir(path) - yield - finally: - os.chdir(old_dir) - def _test_resource(class_, basename, check, **kwargs): """Common code for testing the HTML and CSS classes.""" @@ -63,13 +49,13 @@ def _test_resource(class_, basename, check, **kwargs): check(class_(file_obj=fd, **kwargs)) with open(absolute_filename, 'rb') as fd: content = fd.read() - with chdir(os.path.dirname(__file__)): - relative_filename = os.path.join('resources', basename) - check(class_(relative_filename, **kwargs)) - check(class_(string=content, base_url=relative_filename, **kwargs)) - encoding = kwargs.get('encoding') or 'utf8' - check(class_(string=content.decode(encoding), # unicode - base_url=relative_filename, **kwargs)) + py.path.local(os.path.dirname(__file__)).chdir() + relative_filename = os.path.join('resources', basename) + check(class_(relative_filename, **kwargs)) + check(class_(string=content, base_url=relative_filename, **kwargs)) + encoding = kwargs.get('encoding') or 'utf8' + check(class_(string=content.decode(encoding), # unicode + base_url=relative_filename, **kwargs)) with pytest.raises(TypeError): class_(filename='foo', url='bar') @@ -90,38 +76,89 @@ def _assert_equivalent_pdf(pdf_bytes1, pdf_bytes2): assert page1.BleedBox == page2.BleedBox +def _check_doc1(html, has_base_url=True): + """Check that a parsed HTML document looks like resources/doc1.html""" + root = html.etree_element + assert root.tag == 'html' + assert [child.tag for child in root] == ['head', 'body'] + _head, body = root + assert [child.tag for child in body] == ['h1', 'p', 'ul', 'div'] + h1, p, ul, div = body + assert h1.text == 'WeasyPrint test document (with Ünicōde)' + if has_base_url: + url = urljoin(html.base_url, 'pattern.png') + assert url.startswith('file:') + assert url.endswith('weasyprint/tests/resources/pattern.png') + else: + assert html.base_url is None + + +def _run(args, stdin=b''): + stdin = io.BytesIO(stdin) + stdout = io.BytesIO() + try: + __main__.HTML = FakeHTML + __main__.main(args.split(), stdin=stdin, stdout=stdout) + finally: + __main__.HTML = HTML + return stdout.getvalue() + + +class _fake_file(object): + def __init__(self): + self.chunks = [] + + def write(self, data): + self.chunks.append(bytes(data[:])) + + def getvalue(self): + return b''.join(self.chunks) + + +def _png_size(result): + png_bytes, width, height = result + surface = cairo.ImageSurface.create_from_png(io.BytesIO(png_bytes)) + assert (surface.get_width(), surface.get_height()) == (width, height) + return width, height + + +def _round_meta(pages): + """Eliminate errors of floating point arithmetic for metadata. + (eg. 49.99999999999994 instead of 50) + + """ + for page in pages: + anchors = page.anchors + for anchor_name, (pos_x, pos_y) in anchors.items(): + anchors[anchor_name] = round(pos_x, 6), round(pos_y, 6) + links = page.links + for i, link in enumerate(links): + link_type, target, (pos_x, pos_y, width, height) = link + link = ( + link_type, target, (round(pos_x, 6), round(pos_y, 6), + round(width, 6), round(height, 6))) + links[i] = link + bookmarks = page.bookmarks + for i, (level, label, (pos_x, pos_y)) in enumerate(bookmarks): + bookmarks[i] = level, label, (round(pos_x, 6), round(pos_y, 6)) + + @assert_no_logs def test_html_parsing(): """Test the constructor for the HTML class.""" - def check_doc1(html, has_base_url=True): - """Check that a parsed HTML document looks like resources/doc1.html""" - root = html.etree_element - assert root.tag == 'html' - assert [child.tag for child in root] == ['head', 'body'] - _head, body = root - assert [child.tag for child in body] == ['h1', 'p', 'ul', 'div'] - h1, p, ul, div = body - assert h1.text == 'WeasyPrint test document (with Ünicōde)' - if has_base_url: - url = urljoin(html.base_url, 'pattern.png') - assert url.startswith('file:') - assert url.endswith('weasyprint/tests/resources/pattern.png') - else: - assert html.base_url is None - - _test_resource(FakeHTML, 'doc1.html', check_doc1) - _test_resource(FakeHTML, 'doc1_UTF-16BE.html', check_doc1, + _test_resource(FakeHTML, 'doc1.html', _check_doc1) + _test_resource(FakeHTML, 'doc1_UTF-16BE.html', _check_doc1, encoding='UTF-16BE') - with chdir(os.path.dirname(__file__)): - filename = os.path.join('resources', 'doc1.html') - with open(filename) as fd: - string = fd.read() - check_doc1(FakeHTML(string=string, base_url=filename)) - check_doc1(FakeHTML(string=string), has_base_url=False) - string_with_meta = string.replace( - '' + css + b'' + html linked = b'' + html - with chdir(resource_filename('')): - # Reference - html_obj = FakeHTML(string=combined, base_url='dummy.html') - pdf_bytes = html_obj.write_pdf() - png_bytes = html_obj.write_png() - x2_png_bytes = html_obj.write_png(resolution=192) - rotated_png_bytes = FakeHTML(string=combined, base_url='dummy.html', - media_type='screen').write_png() - empty_png_bytes = FakeHTML( - string=b'').write_png() + py.path.local(resource_filename('')).chdir() + # Reference + html_obj = FakeHTML(string=combined, base_url='dummy.html') + pdf_bytes = html_obj.write_pdf() + png_bytes = html_obj.write_png() + x2_png_bytes = html_obj.write_png(resolution=192) + rotated_png_bytes = FakeHTML(string=combined, base_url='dummy.html', + media_type='screen').write_png() + empty_png_bytes = FakeHTML( + string=b'').write_png() check_png_pattern(png_bytes) check_png_pattern(rotated_png_bytes, rotated=True) check_png_pattern(empty_png_bytes, blank=True) - def run(args, stdin=b''): - stdin = io.BytesIO(stdin) - stdout = io.BytesIO() - try: - __main__.HTML = FakeHTML - __main__.main(args.split(), stdin=stdin, stdout=stdout) - finally: - __main__.HTML = HTML - return stdout.getvalue() - tmpdir.chdir() with open(resource_filename('pattern.png'), 'rb') as pattern_fd: pattern_bytes = pattern_fd.read() @@ -327,72 +343,72 @@ def test_command_line_render(tmpdir): tmpdir.join('linked.html').write_binary(linked) tmpdir.join('style.css').write_binary(css) - run('combined.html out1.png') - run('combined.html out2.pdf') + _run('combined.html out1.png') + _run('combined.html out2.pdf') assert tmpdir.join('out1.png').read_binary() == png_bytes _assert_equivalent_pdf(tmpdir.join('out2.pdf').read_binary(), pdf_bytes) - run('combined-UTF-16BE.html out3.png --encoding UTF-16BE') + _run('combined-UTF-16BE.html out3.png --encoding UTF-16BE') assert tmpdir.join('out3.png').read_binary() == png_bytes - run(tmpdir.join('combined.html').strpath + ' out4.png') + _run(tmpdir.join('combined.html').strpath + ' out4.png') assert tmpdir.join('out4.png').read_binary() == png_bytes - run(path2url(tmpdir.join('combined.html')) + ' out5.png') + _run(path2url(tmpdir.join('combined.html')) + ' out5.png') assert tmpdir.join('out5.png').read_binary() == png_bytes - run('linked.html out6.png') # test relative URLs + _run('linked.html out6.png') # test relative URLs assert tmpdir.join('out6.png').read_binary() == png_bytes - run('combined.html out7 -f png') - run('combined.html out8 --format pdf') + _run('combined.html out7 -f png') + _run('combined.html out8 --format pdf') assert tmpdir.join('out7').read_binary() == png_bytes _assert_equivalent_pdf(tmpdir.join('out8').read_binary(), pdf_bytes) - run('no_css.html out9.png') - run('no_css.html out10.png -s style.css') + _run('no_css.html out9.png') + _run('no_css.html out10.png -s style.css') assert tmpdir.join('out9.png').read_binary() != png_bytes assert tmpdir.join('out10.png').read_binary() == png_bytes - stdout = run('--format png combined.html -') + stdout = _run('--format png combined.html -') assert stdout == png_bytes - run('- out11.png', stdin=combined) + _run('- out11.png', stdin=combined) check_png_pattern(tmpdir.join('out11.png').read_binary()) assert tmpdir.join('out11.png').read_binary() == png_bytes - stdout = run('--format png - -', stdin=combined) + stdout = _run('--format png - -', stdin=combined) assert stdout == png_bytes - run('combined.html out13.png --media-type screen') - run('combined.html out12.png -m screen') - run('linked.html out14.png -m screen') + _run('combined.html out13.png --media-type screen') + _run('combined.html out12.png -m screen') + _run('linked.html out14.png -m screen') assert tmpdir.join('out12.png').read_binary() == rotated_png_bytes assert tmpdir.join('out13.png').read_binary() == rotated_png_bytes assert tmpdir.join('out14.png').read_binary() == rotated_png_bytes - stdout = run('-f pdf combined.html -') + stdout = _run('-f pdf combined.html -') assert stdout.count(b'attachment') == 0 - stdout = run('-f pdf -a pattern.png combined.html -') + stdout = _run('-f pdf -a pattern.png combined.html -') assert stdout.count(b'attachment') == 1 - stdout = run('-f pdf -a style.css -a pattern.png combined.html -') + stdout = _run('-f pdf -a style.css -a pattern.png combined.html -') assert stdout.count(b'attachment') == 2 - stdout = run('-f png -r 192 linked.html -') + stdout = _run('-f png -r 192 linked.html -') assert stdout == x2_png_bytes - stdout = run('-f png --resolution 192 linked.html -') - assert run('linked.html - -f png --resolution 192') == x2_png_bytes + stdout = _run('-f png --resolution 192 linked.html -') + assert _run('linked.html - -f png --resolution 192') == x2_png_bytes assert stdout == x2_png_bytes os.mkdir('subdirectory') - os.chdir('subdirectory') + py.path.local('subdirectory').chdir() with capture_logs() as logs: - stdout = run('--format png - -', stdin=combined) + stdout = _run('--format png - -', stdin=combined) assert len(logs) == 1 assert logs[0].startswith('ERROR: Failed to load image') assert stdout == empty_png_bytes - stdout = run('--format png --base-url .. - -', stdin=combined) + stdout = _run('--format png --base-url .. - -', stdin=combined) assert stdout == png_bytes @@ -473,17 +489,11 @@ def test_low_level_api(): assert (width, height) == (16, 16) check_png_pattern(png_bytes, x2=True) - def png_size(result): - png_bytes, width, height = result - surface = cairo.ImageSurface.create_from_png(io.BytesIO(png_bytes)) - assert (surface.get_width(), surface.get_height()) == (width, height) - return width, height - document = html.render([css], enable_hinting=True) page, = document.pages assert (page.width, page.height) == (8, 8) # A resolution that is not multiple of 96: - assert png_size(document.write_png(resolution=145.2)) == (13, 13) + assert _png_size(document.write_png(resolution=145.2)) == (13, 13) document = FakeHTML(string=''' -

Hello World L!

'''), - [('p', 'Block', [ + assert_tree(parse(''' + +

Hello World L!

'''), [ + ('p', 'Block', [ ('p', 'Text', 'Hello '), ('em', 'Inline', [ ('em', 'Text', 'World '), @@ -168,7 +165,6 @@ def test_box_tree(): @assert_no_logs def test_html_entities(): - """Test the management of HTML entities.""" for quote in ['"', '"', '"', '"']: assert_tree(parse('

{0}abc{1}'.format(quote, quote)), [ ('p', 'Block', [ @@ -176,8 +172,7 @@ def test_html_entities(): @assert_no_logs -def test_inline_in_block(): - """Test the management of inline boxes in block boxes.""" +def test_inline_in_block_1(): source = '

Hello, World!\n

Lipsum.

' expected = [ ('div', 'Block', [ @@ -194,6 +189,9 @@ def test_inline_in_block(): box = build.inline_in_block(box) assert_tree(box, expected) + +@assert_no_logs +def test_inline_in_block_2(): source = '

Lipsum.

Hello, World!\n
' expected = [ ('div', 'Block', [ @@ -210,6 +208,9 @@ def test_inline_in_block(): box = build.inline_in_block(box) assert_tree(box, expected) + +@assert_no_logs +def test_inline_in_block_3(): # Absolutes are left in the lines to get their static position later. source = '''

Hello World!

''' @@ -227,6 +228,9 @@ def test_inline_in_block(): box = build.block_in_inline(box) assert_tree(box, expected) + +@assert_no_logs +def test_inline_in_block_4(): # Floats are pull to the top of their containing blocks source = '

Hello World!

' box = parse(source) @@ -244,14 +248,13 @@ def test_inline_in_block(): @assert_no_logs def test_block_in_inline(): - """Test the management of block boxes in inline boxes.""" box = parse(''' - -

Lorem ipsum dolor sit - amet,conse

''') + +

Lorem ipsum dolor sit + amet,conse''') box = build.inline_in_block(box) assert_tree(box, [ ('body', 'Line', [ @@ -266,7 +269,7 @@ def test_block_in_inline(): ('span', 'Line', [ ('span', 'Text', 'sit')])]), # No whitespace processing here. - ('strong', 'Text', '\n '), + ('strong', 'Text', '\n '), ('span', 'Block', [ # This block is "pulled up" ('span', 'Line', [ ('span', 'Text', 'amet,')])])]), @@ -295,7 +298,7 @@ def test_block_in_inline(): ('em', 'Inline', [ ('strong', 'Inline', [ # Whitespace processing not done yet. - ('strong', 'Text', '\n ')])])])]), + ('strong', 'Text', '\n ')])])])]), ('span', 'Block', [ ('span', 'Line', [ ('span', 'Text', 'amet,')])]), @@ -320,15 +323,14 @@ def test_block_in_inline(): @assert_no_logs def test_styles(): - """Test the application of CSS to HTML.""" box = parse(''' - -

Lorem ipsum dolor sit - amet,consectetur

''') + +

Lorem ipsum dolor sit + amet,consectetur

''') box = build.inline_in_block(box) box = build.block_in_inline(box) @@ -345,17 +347,16 @@ def test_styles(): @assert_no_logs def test_whitespace(): - """Test the management of white spaces.""" # TODO: test more cases # http://www.w3.org/TR/CSS21/text.html#white-space-model assert_tree(parse_all(''' -

Lorem \t\r\n ipsum\t dolor - sit - amet - consectetur.

-
\t  foo\n
-
\t  foo\n
-
\t  foo\n
+

Lorem \t\r\n ipsum\t dolor + sit + amet + consectetur.

+
\t  foo\n
+
\t  foo\n
+
\t  foo\n
'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -384,27 +385,25 @@ def test_whitespace(): @assert_no_logs -def test_page_style(): - """Test the management of page styles.""" +@pytest.mark.parametrize('page_type, top, right, bottom, left', ( + (PageType(side='left', first=True, blank=False, name=None), 20, 3, 3, 10), + (PageType(side='right', first=True, blank=False, name=None), 20, 10, 3, 3), + (PageType(side='left', first=False, blank=False, name=None), 10, 3, 3, 10), + (PageType(side='right', first=False, blank=False, name=None), + 10, 10, 3, 3), +)) +def test_page_style(page_type, top, right, bottom, left): document = FakeHTML(string=''' - + ''') style_for, cascaded_styles, computed_styles = get_all_computed_styles( document) - def assert_page_margins(page_type, top, right, bottom, left): - """Check the page margin values.""" - style = style_for(page_type) - assert style['margin_top'] == (top, 'px') - assert style['margin_right'] == (right, 'px') - assert style['margin_bottom'] == (bottom, 'px') - assert style['margin_left'] == (left, 'px') - # Force the generation of the style for all possible page types as it's # generally only done during the rendering for needed page types. standard_page_type = PageType( @@ -412,28 +411,20 @@ def test_page_style(): set_page_type_computed_styles( standard_page_type, cascaded_styles, computed_styles, document) - assert_page_margins( - PageType(side='left', first=True, blank=False, name=None), - top=20, right=3, bottom=3, left=10) - assert_page_margins( - PageType(side='right', first=True, blank=False, name=None), - top=20, right=10, bottom=3, left=3) - assert_page_margins( - PageType(side='left', first=False, blank=False, name=None), - top=10, right=3, bottom=3, left=10) - assert_page_margins( - PageType(side='right', first=False, blank=False, name=None), - top=10, right=10, bottom=3, left=3) + style = style_for(page_type) + assert style['margin_top'] == (top, 'px') + assert style['margin_right'] == (right, 'px') + assert style['margin_bottom'] == (bottom, 'px') + assert style['margin_left'] == (left, 'px') @assert_no_logs -def test_images(): - """Test images that may or may not be available.""" +def test_images_1(): with capture_logs() as logs: result = parse_all(''' -

No srcInexistent src

+

No srcInexistent src

''') assert len(logs) == 1 assert 'ERROR: Failed to load image' in logs[0] @@ -447,6 +438,9 @@ def test_images(): ('img', 'Inline', [ ('img', 'Text', 'Inexistent src')])])])]) + +@assert_no_logs +def test_images_2(): with capture_logs() as logs: result = parse_all('

No base_url', base_url=None) @@ -460,26 +454,27 @@ def test_images(): @assert_no_logs -def test_tables(): +def test_tables_1(): # Rules in http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes + # Rule 1.3 # Also table model: http://www.w3.org/TR/CSS21/tables.html#model assert_tree(parse_all(''' - - - foo - bar - - - - - - - top caption - - baz - - + + + foo + bar + + + + + + + top caption + + baz + + '''), [ ('x-table', 'Block', [ ('x-caption', 'TableCaption', [ @@ -508,10 +503,13 @@ def test_tables(): ('x-tfoot', 'TableRowGroup', [])]), ('x-caption', 'TableCaption', [])])]) + +@assert_no_logs +def test_tables_2(): # Rules 1.4 and 3.1 assert_tree(parse_all(''' - foo - bar + foo + bar '''), [ ('body', 'Block', [ ('body', 'Table', [ @@ -524,19 +522,22 @@ def test_tables(): ('span', 'Line', [ ('span', 'Text', 'bar')])])])])])])]) + +@assert_no_logs +def test_tables_3(): # http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes # Rules 1.1 and 1.2 # Rule XXX (not in the spec): column groups have at least one column child assert_tree(parse_all(''' - - 1 - - 2 - 3 - - 4 - - + + 1 + + 2 + 3 + + 4 + + '''), [ ('body', 'Block', [ ('body', 'Table', [ @@ -545,6 +546,9 @@ def test_tables(): ('ins', 'TableColumnGroup', [ ('ins', 'TableColumn', [])])])])]) + +@assert_no_logs +def test_tables_4(): # Rules 2.1 then 2.3 assert_tree(parse_all('foo

'), [ ('x-table', 'Block', [ @@ -557,6 +561,9 @@ def test_tables(): ('x-table', 'Text', 'foo ')])]), ('div', 'Block', [])])])])])])]) + +@assert_no_logs +def test_tables_5(): # Rule 2.2 assert_tree(parse_all('' '
'), [ @@ -568,6 +575,9 @@ def test_tables(): ('div', 'Block', [])]), ('x-td', 'TableCell', [])])])])])]) + +@assert_no_logs +def test_tables_6(): # TODO: re-enable this once we support inline-table # Rule 3.2 assert_tree(parse_all(''), [ @@ -578,13 +588,16 @@ def test_tables(): ('span', 'TableRowGroup', [ ('x-tr', 'TableRow', [])])])])])])]) + +@assert_no_logs +def test_tables_7(): # Rule 3.1 # Also, rule 1.3 does not apply: whitespace before and after is preserved assert_tree(parse_all(''' - - - - + + + + '''), [ ('body', 'Line', [ ('span', 'Inline', [ @@ -599,6 +612,9 @@ def test_tables(): ('em', 'TableCell', [])])])])]), ('span', 'Text', ' ')])])]) + +@assert_no_logs +def test_tables_8(): # Rule 3.2 assert_tree(parse_all('\t'), [ ('body', 'Block', [ @@ -607,6 +623,9 @@ def test_tables(): ('x-tr', 'TableRow', []), ('x-tr', 'TableRow', [])])])])]) + +@assert_no_logs +def test_tables_9(): assert_tree(parse_all('\n'), [ ('body', 'Block', [ ('body', 'Table', [ @@ -633,10 +652,10 @@ def test_table_style(): @assert_no_logs def test_column_style(): html = parse_all(''' - - - -
+ + + +
''') body, = html.children wrapper, = body.children @@ -652,15 +671,15 @@ def test_column_style(): @assert_no_logs def test_nested_grid_x(): html = parse_all(''' - - - - - - - - -
+ + + + + + + + +
''') body, = html.children wrapper, = body.children @@ -671,41 +690,38 @@ def test_nested_grid_x(): @assert_no_logs -def test_colspan_rowspan(): - """ - +---+---+---+ - | A | B | C | # - +---+---+---+ - | D | E | # - +---+---+ +---+ - | F ...| | | <-- overlap - +---+---+---+ + - | H | # # | G | - +---+---+ + + - | I | J | # | | - +---+---+ +---+ +def test_colspan_rowspan_1(): + # +---+---+---+ + # | A | B | C | X + # +---+---+---+ + # | D | E | X + # +---+---+ +---+ + # | F ...| | | <-- overlap + # +---+---+---+ + + # | H | X X | G | + # +---+---+ + + + # | I | J | X | | + # +---+---+ +---+ - # empty cells - - """ + # X: empty cells html = parse_all(''' - - - - - - - - - - - -
A B C -
D E -
F G -
H -
I J -
+ + + + + + + + + + + +
A B C +
D E +
F G +
H +
I J +
''') body, = html.children wrapper, = body.children @@ -733,6 +749,9 @@ def test_colspan_rowspan(): [1, 1], ] + +@assert_no_logs +def test_colspan_rowspan_2(): # A cell box cannot extend beyond the last row box of a table. html = parse_all(''' @@ -764,31 +783,31 @@ def test_colspan_rowspan(): @assert_no_logs -def test_before_after(): - """Test the ::before and ::after pseudo-elements.""" +def test_before_after_1(): assert_tree(parse_all(''' - -

-
-
+ +

+
+
'''), [ # No content in pseudo-element, no box generated ('p', 'Block', []), ('div', 'Block', []), ('section', 'Block', [])]) + +@assert_no_logs +def test_before_after_2(): assert_tree(parse_all(''' - -

- c -

+ +

c

'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -798,11 +817,14 @@ def test_before_after(): ('p::after', 'Inline', [ ('p::after', 'Text', 'de')])])])]) + +@assert_no_logs +def test_before_after_3(): assert_tree(parse_all(''' - -

some text

+ +

some text

'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -811,13 +833,16 @@ def test_before_after(): ('a::before', 'Text', '[some url] ')]), ('a', 'Text', 'some text')])])])]) + +@assert_no_logs +def test_before_after_4(): assert_tree(parse_all(''' - -

Lorem ipsum dolor sit amet

+ +

Lorem ipsum dolor sit amet

'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -834,18 +859,22 @@ def test_before_after(): ('q', 'Text', ' sit amet'), ('q::after', 'Inline', [ ('q::after', 'Text', ' »')])])])])]) + + +@assert_no_logs +def test_before_after_5(): with capture_logs() as logs: assert_tree(parse_all(''' - -

c

+ /* Invalid, ignored in favor of the one above. + Regression test: this used to crash: */ + content: some-function(nested-function(something)); + } + +

c

'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -860,45 +889,47 @@ def test_before_after(): @assert_no_logs -def test_counters(): - """Test counter-reset, counter-increment, content: counter() counters()""" +def test_counters_1(): assert_tree(parse_all(''' - -

-

-

-

-

-

-

-

-

-

-

-

'''), [ + +

+

+

+

+

+

+

+

+

+

+

+

'''), [ ('p', 'Block', [ ('p', 'Line', [ ('p::before', 'Inline', [ ('p::before', 'Text', counter)])])]) for counter in '0 1 3 2 4 6 -11 -9 -7 44 46 48'.split()]) + +@assert_no_logs +def test_counters_2(): assert_tree(parse_all(''' -
    -
  1. -
  2. -
  3. -
    1. -
    2. -
    3. -
    4. -
  4. -
  5. -
'''), [ +
    +
  1. +
  2. +
  3. +
    1. +
    2. +
    3. +
    4. +
  4. +
  5. +
'''), [ ('ol', 'Block', [ ('li', 'Block', [ ('li', 'Line', [ @@ -927,16 +958,19 @@ def test_counters(): ('li', 'Line', [ ('li::marker', 'Text', '5.')])])])]) + +@assert_no_logs +def test_counters_3(): assert_tree(parse_all(''' - -
-

-

-

-
-

'''), [ + +
+

+

+

+
+

'''), [ ('div', 'Block', [ ('p', 'Block', [ ('p', 'Line', [ @@ -951,20 +985,23 @@ def test_counters(): ('p', 'Line', [ ('p::marker', 'Text', '1.')])])]) + +@assert_no_logs +def test_counters_4(): assert_tree(parse_all(''' - - -

-

-

-

-
-

-
- '''), [ + + +

+

+

+

+
+

+
+ '''), [ ('section', 'Block', [ ('section', 'Block', [ ('section', 'Line', [ @@ -994,16 +1031,19 @@ def test_counters(): ('h1::before', 'Inline', [ ('h1::before', 'Text', '3')])])])])]) + +@assert_no_logs +def test_counters_5(): assert_tree(parse_all(''' - -
- - Scope created now, deleted after the div - -
-

'''), [ + +
+ + Scope created now, deleted after the div + +
+

'''), [ ('div', 'Block', [ ('div', 'Line', [ ('span', 'Inline', [ @@ -1014,33 +1054,35 @@ def test_counters(): ('p::before', 'Inline', [ ('p::before', 'Text', '0')])])])]) + +@assert_no_logs +def test_counters_6(): # counter-increment may interfere with display: list-item assert_tree(parse_all(''' -

'''), [ +

'''), [ ('p', 'Block', [ ('p', 'Line', [ ('p::marker', 'Text', '0.')])])]) @assert_no_logs -def test_counter_styles(): - """Test the various counter styles.""" +def test_counter_styles_1(): assert_tree(parse_all(''' - -

-

-

-

-

+ +

+

+

+

+

'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -1048,29 +1090,32 @@ def test_counter_styles(): ('p::before', 'Text', counter)])])]) for counter in '-- • ◦ ▪ -7'.split()]) + +@assert_no_logs +def test_counter_styles_2(): assert_tree(parse_all(''' - -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+ +

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

'''), [ ('p', 'Block', [ ('p', 'Line', [ @@ -1079,8 +1124,10 @@ def test_counter_styles(): for counter in '''-1986 -1985 -11 -10 -09 -08 -01 00 01 02 09 10 11 99 100 101 4135 4136'''.split()]) - # Same test as above, but short-circuit HTML and boxes +@assert_no_logs +def test_counter_styles_3(): + # Same test as above, but short-circuit HTML and boxes assert [counters.format(value, 'decimal-leading-zero') for value in [ -1986, -1985, -11, -10, -9, -8, @@ -1093,9 +1140,12 @@ def test_counter_styles(): 99 100 101 4135 4136 '''.split() + +@assert_no_logs +def test_counter_styles_4(): # Now that we’re confident that they do the same, use the shorter form. -# http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-007.htm + # http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-007.htm assert [counters.format(value, 'lower-roman') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, @@ -1109,7 +1159,10 @@ def test_counter_styles(): mmmmcmxcix 5000 5001 '''.split() -# http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-008.htm + +@assert_no_logs +def test_counter_styles_5(): + # http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-008.htm assert [counters.format(value, 'upper-roman') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, @@ -1123,6 +1176,9 @@ def test_counter_styles(): MMMMCMXCIX 5000 5001 '''.split() + +@assert_no_logs +def test_counter_styles_6(): assert [counters.format(value, 'lower-alpha') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, @@ -1132,6 +1188,9 @@ def test_counter_styles(): -1986 -1985 -1 0 a b c d y z aa ab ac bxz bya '''.split() + +@assert_no_logs +def test_counter_styles_7(): assert [counters.format(value, 'upper-alpha') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, @@ -1141,6 +1200,9 @@ def test_counter_styles(): -1986 -1985 -1 0 A B C D Y Z AA AB AC BXZ BYA '''.split() + +@assert_no_logs +def test_counter_styles_8(): assert [counters.format(value, 'lower-latin') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, @@ -1150,6 +1212,9 @@ def test_counter_styles(): -1986 -1985 -1 0 a b c d y z aa ab ac bxz bya '''.split() + +@assert_no_logs +def test_counter_styles_9(): assert [counters.format(value, 'upper-latin') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, @@ -1159,7 +1224,10 @@ def test_counter_styles(): -1986 -1985 -1 0 A B C D Y Z AA AB AC BXZ BYA '''.split() -# http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-009.htm + +@assert_no_logs +def test_counter_styles_10(): + # http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-009.htm assert [counters.format(value, 'georgian') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, @@ -1176,7 +1244,10 @@ def test_counter_styles(): ჵჰშჟთ 20000 20001 '''.split() -# http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-010.htm + +@assert_no_logs +def test_counter_styles_11(): + # http://test.csswg.org/suites/css2.1/20110323/html4/content-counter-010.htm assert [counters.format(value, 'armenian') for value in [ -1986, -1985, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, @@ -1196,24 +1267,21 @@ def test_counter_styles(): @assert_no_logs def test_margin_boxes(): - """ - Test that the correct margin boxes are created. - """ page_1, page_2 = render_pages(''' - -

lorem ipsum + +

lorem ipsum ''') assert page_1.children[0].element_tag == 'html' assert page_2.children[0].element_tag == 'html' @@ -1231,23 +1299,22 @@ def test_margin_boxes(): @assert_no_logs -def test_margin_box_string_set(): - """Test string-set / string() in margin boxes.""" +def test_margin_box_string_set_1(): # Test that both pages get string in the `bottom-center` margin box page_1, page_2 = render_pages(''' - -

first assignment

-
+ +

first assignment

+
''') html, bottom_center = page_2.children @@ -1260,18 +1327,21 @@ def test_margin_box_string_set(): text_box, = line_box.children assert text_box.text == 'first assignment' + +@assert_no_logs +def test_margin_box_string_set_2(): def simple_string_set_test(content_val, extra_style=""): page_1, = render_pages(''' - -

first assignment

+ +

first assignment

''' % dict(content_val=content_val, extra_style=extra_style)) html, top_center = page_1.children @@ -1290,18 +1360,21 @@ def test_margin_box_string_set(): else: simple_string_set_test(value) + +@assert_no_logs +def test_margin_box_string_set_3(): # Test `first` (default value) ie. use the first assignment on the page page_1, = render_pages(''' - -

first assignment

-

Second assignment

+ +

first assignment

+

Second assignment

''') html, top_center = page_1.children @@ -1309,21 +1382,24 @@ def test_margin_box_string_set(): text_box, = line_box.children assert text_box.text == 'first assignment' + +@assert_no_logs +def test_margin_box_string_set_4(): # test `first-except` ie. exclude from page on which value is assigned page_1, page_2 = render_pages(''' - -

first_excepted

-
+ +

first_excepted

+
''') html, top_center = page_1.children assert len(top_center.children) == 0 @@ -1333,18 +1409,21 @@ def test_margin_box_string_set(): text_box, = line_box.children assert text_box.text == 'first_excepted' + +@assert_no_logs +def test_margin_box_string_set_5(): # Test `last` ie. use the most-recent assignment page_1, = render_pages(''' - -

String set

-

Second assignment

+ +

String set

+

Second assignment

''') html, top_center = page_1.children[:2] @@ -1353,34 +1432,37 @@ def test_margin_box_string_set(): text_box, = line_box.children assert text_box.text == 'Second assignment' + +@assert_no_logs +def test_margin_box_string_set_6(): # Test multiple complex string-set values page_1, = render_pages(''' - -
    -
  • first -
  • -
      -
    • second + +
        +
      • first +
      • +
          +
        • second ''') html, top_center, bottom_center = page_1.children @@ -1396,18 +1478,18 @@ def test_margin_box_string_set(): def test_page_counters(): """Test page-based counters.""" pages = render_pages(''' - -

          lorem ipsum dolor + +

          lorem ipsum dolor ''') for page_number, page in enumerate(pages, 1): html, bottom_center = page.children @@ -1416,8 +1498,20 @@ def test_page_counters(): assert text_box.text == 'Page {0} of 3.'.format(page_number) +black = (0, 0, 0, 1) +red = (1, 0, 0, 1) +green = (0, 1, 0, 1) # lime in CSS +blue = (0, 0, 1, 1) +yellow = (1, 1, 0, 1) +black_3 = ('solid', 3, black) +red_1 = ('solid', 1, red) +yellow_5 = ('solid', 5, yellow) +green_5 = ('solid', 5, green) +dashed_blue_5 = ('dashed', 5, blue) + + @assert_no_logs -def test_border_collapse(): +def test_border_collapse_1(): html = parse_all('

') body, = html.children table_wrapper, = body.children @@ -1425,35 +1519,19 @@ def test_border_collapse(): assert isinstance(table, boxes.TableBox) assert not hasattr(table, 'collapsed_border_grid') - def get_grid(html): - html = parse_all(html) - body, = html.children - table_wrapper, = body.children - table, = table_wrapper.children - return tuple( - [[(style, width, color) if width else None - for _score, (style, width, color) in column] - for column in grid] - for grid in table.collapsed_border_grid) - - grid = get_grid('
') + grid = _get_grid('
') assert grid == ([], []) - black = (0, 0, 0, 1) - red = (1, 0, 0, 1) - green = (0, 1, 0, 1) # lime in CSS - blue = (0, 0, 1, 1) - yellow = (1, 1, 0, 1) - vertical_borders, horizontal_borders = get_grid(''' - - - - -
A B
C D
+@assert_no_logs +def test_border_collapse_2(): + vertical_borders, horizontal_borders = _get_grid(''' + + + + +
A B
C D
''') - black_3 = ('solid', 3, black) - red_1 = ('solid', 1, red) assert vertical_borders == [ [black_3, red_1, black_3], [black_3, red_1, black_3], @@ -1464,13 +1542,16 @@ def test_border_collapse(): [black_3, black_3], ] + +@assert_no_logs +def test_border_collapse_3(): # hidden vs. none - vertical_borders, horizontal_borders = get_grid(''' - - - - -
A B
C D
+ vertical_borders, horizontal_borders = _get_grid(''' + + + + +
A B
C D
''') assert vertical_borders == [ [black_3, None, None], @@ -1482,19 +1563,19 @@ def test_border_collapse(): [black_3, black_3], ] - yellow_5 = ('solid', 5, yellow) - green_5 = ('solid', 5, green) - dashed_blue_5 = ('dashed', 5, blue) - vertical_borders, horizontal_borders = get_grid(''' - - - - - - - - -
+ +@assert_no_logs +def test_border_collapse_4(): + vertical_borders, horizontal_borders = _get_grid(''' + + + + + + + + +
''') assert vertical_borders == [ [yellow_5, black_3, red_1, yellow_5], @@ -1510,8 +1591,11 @@ def test_border_collapse(): [yellow_5, yellow_5, yellow_5], ] + +@assert_no_logs +def test_border_collapse_5(): # rowspan and colspan - vertical_borders, horizontal_borders = get_grid(''' + vertical_borders, horizontal_borders = _get_grid(''' diff --git a/weasyprint/tests/test_css_descriptors.py b/weasyprint/tests/test_css_descriptors.py index 9bf3e441..eed59c80 100644 --- a/weasyprint/tests/test_css_descriptors.py +++ b/weasyprint/tests/test_css_descriptors.py @@ -16,8 +16,7 @@ from .testing_utils import assert_no_logs, capture_logs @assert_no_logs -def test_font_face(): - """Test the ``font-face`` rule.""" +def test_font_face_1(): stylesheet = tinycss2.parse_stylesheet( '@font-face {' ' font-family: Gentium Hard;' @@ -32,6 +31,9 @@ def test_font_face(): assert src == ( 'src', (('external', 'http://example.com/fonts/Gentium.woff'),)) + +@assert_no_logs +def test_font_face_2(): stylesheet = tinycss2.parse_stylesheet( '@font-face {' ' font-family: "Fonty Smiley";' @@ -53,6 +55,9 @@ def test_font_face(): assert font_weight == ('font_weight', 200) assert font_stretch == ('font_stretch', 'condensed') + +@assert_no_logs +def test_font_face_3(): stylesheet = tinycss2.parse_stylesheet( '@font-face {' ' font-family: Gentium Hard;' @@ -66,6 +71,9 @@ def test_font_face(): assert font_family == ('font_family', 'Gentium Hard') assert src == ('src', (('local', None),)) + +@assert_no_logs +def test_font_face_4(): # See bug #487 stylesheet = tinycss2.parse_stylesheet( '@font-face {' @@ -81,8 +89,7 @@ def test_font_face(): assert src == ('src', (('local', 'Gentium Hard'),)) -def test_bad_font_face(): - """Test bad ``font-face`` rules.""" +def test_font_face_bad_1(): stylesheet = tinycss2.parse_stylesheet( '@font-face {' ' font-family: "Bad Font";' @@ -108,6 +115,8 @@ def test_bad_font_face(): 'WARNING: Ignored `font-weight: bolder` at 1:111, invalid value.', 'WARNING: Ignored `font-stretch: wrong` at 1:133, invalid value.'] + +def test_font_face_bad_2(): stylesheet = tinycss2.parse_stylesheet('@font-face{}') with capture_logs() as logs: descriptors = [] @@ -118,6 +127,8 @@ def test_bad_font_face(): assert logs == [ "WARNING: Missing src descriptor in '@font-face' rule at 1:1"] + +def test_font_face_bad_3(): stylesheet = tinycss2.parse_stylesheet('@font-face{src: url(test.woff)}') with capture_logs() as logs: descriptors = [] @@ -128,6 +139,8 @@ def test_bad_font_face(): assert logs == [ "WARNING: Missing font-family descriptor in '@font-face' rule at 1:1"] + +def test_font_face_bad_4(): stylesheet = tinycss2.parse_stylesheet('@font-face{font-family: test}') with capture_logs() as logs: descriptors = [] @@ -138,6 +151,8 @@ def test_bad_font_face(): assert logs == [ "WARNING: Missing src descriptor in '@font-face' rule at 1:1"] + +def test_font_face_bad_5(): stylesheet = tinycss2.parse_stylesheet( '@font-face { font-family: test; src: wrong }') with capture_logs() as logs: @@ -150,6 +165,8 @@ def test_bad_font_face(): 'WARNING: Ignored `src: wrong ` at 1:33, invalid value.', "WARNING: Missing src descriptor in '@font-face' rule at 1:1"] + +def test_font_face_bad_6(): stylesheet = tinycss2.parse_stylesheet( '@font-face { font-family: good, bad; src: url(test.woff) }') with capture_logs() as logs: @@ -162,6 +179,8 @@ def test_bad_font_face(): 'WARNING: Ignored `font-family: good, bad` at 1:14, invalid value.', "WARNING: Missing font-family descriptor in '@font-face' rule at 1:1"] + +def test_font_face_bad_7(): stylesheet = tinycss2.parse_stylesheet( '@font-face { font-family: good, bad; src: really bad }') with capture_logs() as logs: diff --git a/weasyprint/tests/test_css_validation.py b/weasyprint/tests/test_css_validation.py index 1295039f..12f1b3e6 100644 --- a/weasyprint/tests/test_css_validation.py +++ b/weasyprint/tests/test_css_validation.py @@ -53,182 +53,224 @@ def test_not_print(): def test_function(): assert expand_to_dict('clip: rect(1px, 3em, auto, auto)') == { 'clip': ((1, 'px'), (3, 'em'), 'auto', 'auto')} - assert_invalid('clip: square(1px, 3em, auto, auto)') - assert_invalid('clip: rect(1px, 3em, auto auto)', 'invalid') - assert_invalid('clip: rect(1px, 3em, auto)') - assert_invalid('clip: rect(1px, 3em / auto)') @assert_no_logs -def test_counters(): - assert expand_to_dict('counter-reset: foo bar 2 baz') == { - 'counter_reset': (('foo', 0), ('bar', 2), ('baz', 0))} - assert expand_to_dict('counter-increment: foo bar 2 baz') == { - 'counter_increment': (('foo', 1), ('bar', 2), ('baz', 1))} - assert expand_to_dict('counter-reset: foo') == { - 'counter_reset': (('foo', 0),)} - assert expand_to_dict('counter-reset: FoO') == { - 'counter_reset': (('FoO', 0),)} - assert expand_to_dict('counter-increment: foo bAr 2 Bar') == { - 'counter_increment': (('foo', 1), ('bAr', 2), ('Bar', 1))} - assert expand_to_dict('counter-reset: none') == { - 'counter_reset': ()} - assert expand_to_dict( - 'counter-reset: foo none', 'Invalid counter name') == {} - assert expand_to_dict( - 'counter-reset: foo initial', 'Invalid counter name') == {} - assert_invalid('counter-reset: foo 3px') - assert_invalid('counter-reset: 3') +@pytest.mark.parametrize('rule', ( + 'clip: square(1px, 3em, auto, auto)', + 'clip: rect(1px, 3em, auto auto)', + 'clip: rect(1px, 3em, auto)', + 'clip: rect(1px, 3em / auto)', +)) +def test_function_invalid(rule): + assert_invalid(rule) @assert_no_logs -def test_spacing(): - assert expand_to_dict('letter-spacing: normal') == { - 'letter_spacing': 'normal'} - assert expand_to_dict('letter-spacing: 3px') == { - 'letter_spacing': (3, 'px')} - assert_invalid('letter-spacing: 3') - assert expand_to_dict( - 'letter_spacing: normal', 'did you mean letter-spacing') == {} +@pytest.mark.parametrize('rule, result', ( + ('counter-reset: foo bar 2 baz', { + 'counter_reset': (('foo', 0), ('bar', 2), ('baz', 0))}), + ('counter-increment: foo bar 2 baz', { + 'counter_increment': (('foo', 1), ('bar', 2), ('baz', 1))}), + ('counter-reset: foo', {'counter_reset': (('foo', 0),)}), + ('counter-reset: FoO', {'counter_reset': (('FoO', 0),)}), + ('counter-increment: foo bAr 2 Bar', { + 'counter_increment': (('foo', 1), ('bAr', 2), ('Bar', 1))}), + ('counter-reset: none', {'counter_reset': ()}), +)) +def test_counters(rule, result): + assert expand_to_dict(rule) == result - assert expand_to_dict('word-spacing: normal') == { - 'word_spacing': 'normal'} - assert expand_to_dict('word-spacing: 3px') == { - 'word_spacing': (3, 'px')} - assert_invalid('word-spacing: 3') + +@pytest.mark.parametrize('rule, warning, result', ( + ('counter-reset: foo initial', 'Invalid counter name: initial.', {}), + ('counter-reset: foo none', 'Invalid counter name: none.', {}), +)) +def test_counters_warning(rule, warning, result): + assert expand_to_dict(rule, warning) == result @assert_no_logs -def test_decoration(): - assert expand_to_dict('text-decoration: none') == { - 'text_decoration': 'none'} - assert expand_to_dict('text-decoration: overline') == { - 'text_decoration': frozenset(['overline'])} - # blink is accepted but ignored - assert expand_to_dict('text-decoration: overline blink line-through') == { - 'text_decoration': frozenset(['line-through', 'overline'])} +@pytest.mark.parametrize('rule', ( + 'counter-reset: foo 3px', + 'counter-reset: 3', +)) +def test_counters_invalid(rule): + assert_invalid(rule) @assert_no_logs -def test_size(): - assert expand_to_dict('size: 200px') == { - 'size': ((200, 'px'), (200, 'px'))} - assert expand_to_dict('size: 200px 300pt') == { - 'size': ((200, 'px'), (300, 'pt'))} - assert expand_to_dict('size: auto') == { - 'size': ((210, 'mm'), (297, 'mm'))} - assert expand_to_dict('size: portrait') == { - 'size': ((210, 'mm'), (297, 'mm'))} - assert expand_to_dict('size: landscape') == { - 'size': ((297, 'mm'), (210, 'mm'))} - assert expand_to_dict('size: A3 portrait') == { - 'size': ((297, 'mm'), (420, 'mm'))} - assert expand_to_dict('size: A3 landscape') == { - 'size': ((420, 'mm'), (297, 'mm'))} - assert expand_to_dict('size: portrait A3') == { - 'size': ((297, 'mm'), (420, 'mm'))} - assert expand_to_dict('size: landscape A3') == { - 'size': ((420, 'mm'), (297, 'mm'))} - assert_invalid('size: A3 landscape A3') - assert_invalid('size: A9') - assert_invalid('size: foo') - assert_invalid('size: foo bar') - assert_invalid('size: 20%') +@pytest.mark.parametrize('rule, result', ( + ('letter-spacing: normal', {'letter_spacing': 'normal'}), + ('letter-spacing: 3px', {'letter_spacing': (3, 'px')}), + ('word-spacing: normal', {'word_spacing': 'normal'}), + ('word-spacing: 3px', {'word_spacing': (3, 'px')}), +)) +def test_spacing(rule, result): + assert expand_to_dict(rule) == result @assert_no_logs -def test_transforms(): - assert expand_to_dict('transform: none') == { - 'transform': ()} +def test_spacing_warning(): assert expand_to_dict( - 'transform: translate(6px) rotate(90deg)' - ) == {'transform': (('translate', ((6, 'px'), (0, 'px'))), - ('rotate', math.pi / 2))} - assert expand_to_dict( - 'transform: translate(-4px, 0)' - ) == {'transform': (('translate', ((-4, 'px'), (0, None))),)} - assert expand_to_dict( - 'transform: translate(6px, 20%)' - ) == {'transform': (('translate', ((6, 'px'), (20, '%'))),)} - assert expand_to_dict( - 'transform: scale(2)' - ) == {'transform': (('scale', (2, 2)),)} - assert_invalid('transform: translate(6px 20%)') # missing comma - assert_invalid('transform: lipsumize(6px)') - assert_invalid('transform: foo') - assert_invalid('transform: scale(2) foo') - assert_invalid('transform: 6px') + 'letter_spacing: normal', 'did you mean letter-spacing?') == {} @assert_no_logs -def test_expand_four_sides(): - """Test the 4-value properties.""" - assert expand_to_dict('margin: inherit') == { +@pytest.mark.parametrize('rule', ( + 'letter-spacing: 3', + 'word-spacing: 3', +)) +def test_spacing_invalid(rule): + assert_invalid(rule) + + +@assert_no_logs +@pytest.mark.parametrize('rule, result', ( + ('text-decoration: none', {'text_decoration': 'none'}), + ('text-decoration: overline', { + 'text_decoration': frozenset(['overline'])}), + ('text-decoration: overline blink line-through', { + 'text_decoration': frozenset(['line-through', 'overline'])}), +)) +def test_decoration(rule, result): + assert expand_to_dict(rule) == result + + +@assert_no_logs +@pytest.mark.parametrize('rule, result', ( + ('size: 200px', {'size': ((200, 'px'), (200, 'px'))}), + ('size: 200px 300pt', {'size': ((200, 'px'), (300, 'pt'))}), + ('size: auto', {'size': ((210, 'mm'), (297, 'mm'))}), + ('size: portrait', {'size': ((210, 'mm'), (297, 'mm'))}), + ('size: landscape', {'size': ((297, 'mm'), (210, 'mm'))}), + ('size: A3 portrait', {'size': ((297, 'mm'), (420, 'mm'))}), + ('size: A3 landscape', {'size': ((420, 'mm'), (297, 'mm'))}), + ('size: portrait A3', {'size': ((297, 'mm'), (420, 'mm'))}), + ('size: landscape A3', {'size': ((420, 'mm'), (297, 'mm'))}), +)) +def test_size(rule, result): + assert expand_to_dict(rule) == result + + +@pytest.mark.parametrize('rule', ( + 'size: A3 landscape A3', + 'size: A9', + 'size: foo', + 'size: foo bar', + 'size: 20%', +)) +def test_size_invalid(rule): + assert_invalid(rule) + + +@assert_no_logs +@pytest.mark.parametrize('rule, result', ( + ('transform: none', {'transform': ()}), + ('transform: translate(6px) rotate(90deg)', { + 'transform': ( + ('translate', ((6, 'px'), (0, 'px'))), + ('rotate', math.pi / 2))}), + ('transform: translate(-4px, 0)', { + 'transform': (('translate', ((-4, 'px'), (0, None))),)}), + ('transform: translate(6px, 20%)', { + 'transform': (('translate', ((6, 'px'), (20, '%'))),)}), + ('transform: scale(2)', {'transform': (('scale', (2, 2)),)}), +)) +def test_transforms(rule, result): + assert expand_to_dict(rule) == result + + +@assert_no_logs +@pytest.mark.parametrize('rule', ( + 'transform: translate(6px 20%)', # missing comma + 'transform: lipsumize(6px)', + 'transform: foo', + 'transform: scale(2) foo', + 'transform: 6px', +)) +def test_transforms_invalid(rule): + assert_invalid(rule) + + +@assert_no_logs +@pytest.mark.parametrize('rule, result', ( + ('margin: inherit', { 'margin_top': 'inherit', 'margin_right': 'inherit', 'margin_bottom': 'inherit', 'margin_left': 'inherit', - } - assert expand_to_dict('margin: 1em') == { + }), + ('margin: 1em', { 'margin_top': (1, 'em'), 'margin_right': (1, 'em'), 'margin_bottom': (1, 'em'), 'margin_left': (1, 'em'), - } - assert expand_to_dict('margin: -1em auto 20%') == { + }), + ('margin: -1em auto 20%', { 'margin_top': (-1, 'em'), 'margin_right': 'auto', 'margin_bottom': (20, '%'), 'margin_left': 'auto', - } - assert expand_to_dict('padding: 1em 0') == { + }), + ('padding: 1em 0', { 'padding_top': (1, 'em'), 'padding_right': (0, None), 'padding_bottom': (1, 'em'), 'padding_left': (0, None), - } - assert expand_to_dict('padding: 1em 0 2%') == { + }), + ('padding: 1em 0 2%', { 'padding_top': (1, 'em'), 'padding_right': (0, None), 'padding_bottom': (2, '%'), 'padding_left': (0, None), - } - assert expand_to_dict('padding: 1em 0 2em 5px') == { + }), + ('padding: 1em 0 2em 5px', { 'padding_top': (1, 'em'), 'padding_right': (0, None), 'padding_bottom': (2, 'em'), 'padding_left': (5, 'px'), - } - assert expand_to_dict( - 'padding: 1 2 3 4 5', - 'Expected 1 to 4 token components got 5') == {} - assert_invalid('margin: rgb(0, 0, 0)') - assert_invalid('padding: auto') - assert_invalid('padding: -12px') - assert_invalid('border-width: -3em') - assert_invalid('border-width: 12%') + }), +)) +def test_expand_four_sides(rule, result): + assert expand_to_dict(rule) == result @assert_no_logs -def test_expand_borders(): - """Test the ``border`` property.""" - assert expand_to_dict('border-top: 3px dotted red') == { +def test_expand_four_sides_warning(): + assert expand_to_dict( + 'padding: 1 2 3 4 5', 'Expected 1 to 4 token components got 5') == {} + + +@assert_no_logs +@pytest.mark.parametrize('rule', ( + 'margin: rgb(0, 0, 0)', + 'padding: auto', + 'padding: -12px', + 'border-width: -3em', + 'border-width: 12%', +)) +def test_expand_four_sides_invalid(rule): + assert_invalid(rule) + + +@assert_no_logs +@pytest.mark.parametrize('rule, result', ( + ('border-top: 3px dotted red', { 'border_top_width': (3, 'px'), 'border_top_style': 'dotted', 'border_top_color': (1, 0, 0, 1), # red - } - assert expand_to_dict('border-top: 3px dotted') == { + }), + ('border-top: 3px dotted', { 'border_top_width': (3, 'px'), 'border_top_style': 'dotted', - } - assert expand_to_dict('border-top: 3px red') == { + }), + ('border-top: 3px red', { 'border_top_width': (3, 'px'), 'border_top_color': (1, 0, 0, 1), # red - } - assert expand_to_dict('border-top: solid') == { - 'border_top_style': 'solid', - } - assert expand_to_dict('border: 6px dashed lime') == { + }), + ('border-top: solid', {'border_top_style': 'solid'}), + ('border: 6px dashed lime', { 'border_top_width': (6, 'px'), 'border_top_style': 'dashed', 'border_top_color': (0, 1, 0, 1), # lime @@ -244,42 +286,63 @@ def test_expand_borders(): 'border_right_width': (6, 'px'), 'border_right_style': 'dashed', 'border_right_color': (0, 1, 0, 1), # lime - } + }), +)) +def test_expand_borders(rule, result): + assert expand_to_dict(rule) == result + + +@assert_no_logs +def test_expand_borders_invalid(): assert_invalid('border: 6px dashed left') @assert_no_logs -def test_expand_list_style(): - """Test the ``list_style`` property.""" - assert expand_to_dict('list-style: inherit') == { +@pytest.mark.parametrize('rule, result', ( + ('list-style: inherit', { 'list_style_position': 'inherit', 'list_style_image': 'inherit', 'list_style_type': 'inherit', - } - assert expand_to_dict('list-style: url(../bar/lipsum.png)') == { + }), + ('list-style: url(../bar/lipsum.png)', { 'list_style_image': ('url', 'http://weasyprint.org/bar/lipsum.png'), - } - assert expand_to_dict('list-style: square') == { + }), + ('list-style: square', { 'list_style_type': 'square', - } - assert expand_to_dict('list-style: circle inside') == { + }), + ('list-style: circle inside', { 'list_style_position': 'inside', 'list_style_type': 'circle', - } - assert expand_to_dict('list-style: none circle inside') == { + }), + ('list-style: none circle inside', { 'list_style_position': 'inside', 'list_style_image': ('none', None), 'list_style_type': 'circle', - } - assert expand_to_dict('list-style: none inside none') == { + }), + ('list-style: none inside none', { 'list_style_position': 'inside', 'list_style_image': ('none', None), 'list_style_type': 'none', - } - assert_invalid('list-style: none inside none none') - assert_invalid('list-style: red') - assert_invalid('list-style: circle disc', - 'got multiple type values in a list-style shorthand') + }), +)) +def test_expand_list_style(rule, result): + assert expand_to_dict(rule) == result + + +@assert_no_logs +def test_expand_list_style_warning(): + assert_invalid( + 'list-style: circle disc', + 'got multiple type values in a list-style shorthand') + + +@assert_no_logs +@pytest.mark.parametrize('rule', ( + 'list-style: none inside none none', + 'list-style: red', +)) +def test_expand_list_style_invalid(rule): + assert_invalid(rule) def assert_background(css, **expected): @@ -296,7 +359,6 @@ def assert_background(css, **expected): @assert_no_logs def test_expand_background(): - """Test the ``background`` property.""" assert_background('red', background_color=(1, 0, 0, 1)) assert_background( 'url(lipsum.png)', diff --git a/weasyprint/tests/test_draw.py b/weasyprint/tests/test_draw.py deleted file mode 100644 index 4caff683..00000000 --- a/weasyprint/tests/test_draw.py +++ /dev/null @@ -1,2918 +0,0 @@ -""" - weasyprint.tests.test_draw - -------------------------- - - Test the final, drawn results and compare PNG images pixel per pixel. - - :copyright: Copyright 2011-2014 Simon Sapin and contributors, see AUTHORS. - :license: BSD, see LICENSE for details. - -""" - -import itertools -import os.path -import shutil -import sys -import tempfile - -import cairocffi as cairo - -from .. import HTML -from ..html import HTML_HANDLERS -from ..urls import ensure_url -from .testing_utils import ( - FONTS, FakeHTML, assert_no_logs, capture_logs, requires, resource_filename) - -# RGBA to native-endian ARGB -as_pixel = ( - lambda x: x[:-1][::-1] + x[-1:] - if sys.byteorder == 'little' else - lambda x: x[-1:] + x[:-1]) - -# Short variable names are OK here - -_ = as_pixel(b'\xff\xff\xff\xff') # white -r = as_pixel(b'\xff\x00\x00\xff') # red -B = as_pixel(b'\x00\x00\xff\xff') # blue - - -def assert_pixels(name, expected_width, expected_height, expected_pixels, - html): - """Helper testing the size of the image and the pixels values.""" - assert len(expected_pixels) == expected_height - assert len(expected_pixels[0]) == expected_width * 4 - expected_raw = b''.join(expected_pixels) - _doc, pixels = html_to_pixels(name, expected_width, expected_height, html) - assert_pixels_equal(name, expected_width, expected_height, pixels, - expected_raw) - - -def assert_same_rendering(expected_width, expected_height, documents, - tolerance=0): - """ - Render HTML documents to PNG and check that they render the same, - pixel-per-pixel. - - Each document is passed as a (name, html_source) tuple. - """ - pixels_list = [] - - for name, html in documents: - _doc, pixels = html_to_pixels( - name, expected_width, expected_height, html) - pixels_list.append((name, pixels)) - - _name, reference = pixels_list[0] - for name, pixels in pixels_list[1:]: - assert_pixels_equal(name, expected_width, expected_height, - reference, pixels, tolerance) - - -def assert_different_renderings(expected_width, expected_height, documents): - """ - Render HTML documents to PNG and check that no two documents render - the same. - - Each document is passed as a (name, html_source) tuple. - """ - pixels_list = [] - - for name, html in documents: - _doc, pixels = html_to_pixels( - name, expected_width, expected_height, html) - pixels_list.append((name, pixels)) - - for i, (name_1, pixels_1) in enumerate(pixels_list): - for name_2, pixels_2 in pixels_list[i + 1:]: - if pixels_1 == pixels_2: # pragma: no cover - write_png(name_1, pixels_1, expected_width, expected_height) - # Same as "assert pixels_1 != pixels_2" but the output of - # the assert hook would be gigantic and useless. - assert False, '%s and %s are the same' % (name_1, name_2) - - -def write_png(basename, pixels, width, height): # pragma: no cover - """Take a pixel matrix and write a PNG file.""" - directory = os.path.join(os.path.dirname(__file__), 'results') - if not os.path.isdir(directory): - os.mkdir(directory) - filename = os.path.join(directory, basename + '.png') - cairo.ImageSurface( - cairo.FORMAT_ARGB32, width, height, - data=bytearray(pixels), stride=width * 4 - ).write_to_png(filename) - - -def html_to_pixels(name, expected_width, expected_height, html): - """ - Render an HTML document to PNG, checks its size and return pixel data. - - Also return the document to aid debugging. - """ - document = FakeHTML( - string=html, - # Dummy filename, but in the right directory. - base_url=resource_filename('')) - pixels = document_to_pixels( - document, name, expected_width, expected_height) - return document, pixels - - -def document_to_pixels(document, name, expected_width, expected_height): - """ - Render an HTML document to PNG, checks its size and return pixel data. - """ - surface = document.write_image_surface() - return image_to_pixels(surface, expected_width, expected_height) - - -def image_to_pixels(surface, width, height): - assert (surface.get_width(), surface.get_height()) == (width, height) - # RGB24 is actually the same as ARGB32, with A unused. - assert surface.get_format() in (cairo.FORMAT_ARGB32, cairo.FORMAT_RGB24) - pixels = surface.get_data()[:] - assert len(pixels) == width * height * 4 - return pixels - - -def assert_pixels_equal(name, width, height, raw, expected_raw, tolerance=0): - """ - Take 2 matrices of height by width pixels and assert that they - are the same. - """ - if raw != expected_raw: # pragma: no cover - for i, (value, expected) in enumerate(zip( - list(raw), list(expected_raw) - )): - if abs(value - expected) > tolerance: - write_png(name, raw, width, height) - write_png(name + '.expected', expected_raw, - width, height) - pixel_n = i // 4 - x = pixel_n // width - y = pixel_n % width - i % 4 - pixel = tuple(list(raw[i:i + 4])) - expected_pixel = tuple(list( - expected_raw[i:i + 4])) - assert 0, ( - 'Pixel (%i, %i) in %s: expected rgba%s, got rgba%s' - % (x, y, name, expected_pixel, pixel)) - - -@assert_no_logs -def test_canvas_background(): - """Test the background applied on ```` and/or ```` tags.""" - assert_pixels('all_blue', 10, 10, (10 * [10 * B]), ''' - - - ''') - - assert_pixels('blocks', 10, 10, [ - r + r + r + r + r + r + r + r + r + r, - r + r + r + r + r + r + r + r + r + r, - r + r + B + B + B + B + B + B + r + r, - r + r + B + B + B + B + B + B + r + r, - r + r + B + B + B + B + B + B + r + r, - r + r + B + B + B + B + B + B + r + r, - r + r + B + B + B + B + B + B + r + r, - r + r + r + r + r + r + r + r + r + r, - r + r + r + r + r + r + r + r + r + r, - r + r + r + r + r + r + r + r + r + r, - - ], ''' - - - ''') - - -@assert_no_logs -def test_background_image(): - """Test background images.""" - # pattern.png looks like this: - - # r + B + B + B, - # B + B + B + B, - # B + B + B + B, - # B + B + B + B, - - for name, css, pixels in [ - ('repeat', 'url(pattern.png)', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('repeat_x', 'url(pattern.png) repeat-x', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('repeat_y', 'url(pattern.png) repeat-y', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - - ('left_top', 'url(pattern.png) no-repeat 0 0%', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('center_top', 'url(pattern.png) no-repeat 50% 0px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('right_top', 'url(pattern.png) no-repeat 6px top', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('bottom_6_right_0', 'url(pattern.png) no-repeat bottom 6px right 0', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('left_center', 'url(pattern.png) no-repeat left center', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('center_left', 'url(pattern.png) no-repeat center left', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('center_center', 'url(pattern.png) no-repeat 3px 3px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('right_center', 'url(pattern.png) no-repeat 100% 50%', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - - ('left_bottom', 'url(pattern.png) no-repeat 0% bottom', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('center_bottom', 'url(pattern.png) no-repeat center 6px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('bottom_center', 'url(pattern.png) no-repeat bottom center', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('right_bottom', 'url(pattern.png) no-repeat 6px 100%', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - - ('repeat_x_1px_2px', 'url(pattern.png) repeat-x 1px 2px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + r + B + B + B + r + B + B + B + r + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('repeat_y_local_2px_1px', 'url(pattern.png) repeat-y local 2px 1px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - - ('fixed', 'url(pattern.png) no-repeat fixed', [ - # The image is actually here: - ####### - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # - _ + _ + B + B + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # - _ + _ + B + B + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('fixed_right', 'url(pattern.png) no-repeat fixed right 3px', [ - # x x x x - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + r + B + _ + _, # x - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _, # x - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _, # x - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _, # x - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('fixed_center_center', 'url(pattern.png)no-repeat fixed 50%center', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('multi_under', '''url(pattern.png) no-repeat, - url(pattern.png) no-repeat 2px 1px''', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('multi_over', '''url(pattern.png) no-repeat 2px 1px, - url(pattern.png) no-repeat''', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + r + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ]: - assert_pixels('background_' + name, 14, 16, pixels, ''' - - -

  - ''' % (css,)) - - # Regression test for https://github.com/Kozea/WeasyPrint/issues/217 - assert_pixels('zero_size_background', 10, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - -@assert_no_logs -def test_background_origin(): - """Test the background-origin property.""" - def test_value(value, pixels, css=None): - assert_pixels('background_origin_' + value, 12, 12, pixels, ''' - - - ''' % (css or value,)) - - test_value('border-box', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - test_value('padding-box', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - test_value('content-box', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - - test_value('border-box_clip', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + r + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], css='border-box; background-clip: content-box') - - -@assert_no_logs -def test_background_repeat_space(): - """Test for background-repeat: space""" - assert_pixels('background_repeat_space', 12, 16, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + _ + _ + r + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + _ + _ + r + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + _ + _ + r + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_repeat_space', 12, 14, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + _ + _ + r + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + r + B + B + B + _ + _ + r + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + r + B + B + B + _ + _ + r + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + B + B + B + B + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_repeat_space', 12, 13, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + r + B + B + B + r + B + _, - _ + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + r + B + B + B + r + B + _, - _ + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - -@assert_no_logs -def test_background_repeat_round(): - """Test for background-repeat: round""" - assert_pixels('background_repeat_round', 10, 14, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_repeat_round', 10, 18, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_repeat_round', 10, 14, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_repeat_round', 10, 14, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + r + B + B + B + _, - _ + r + B + B + B + r + B + B + B + _, - _ + r + B + B + B + r + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - -@assert_no_logs -def test_background_clip(): - """Test the background-clip property.""" - def test_value(value, pixels): - assert_pixels('background_clip_' + value, 8, 8, pixels, ''' - - - ''' % (value,)) - - test_value('#00f border-box', [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _, - ]) - test_value('#00f padding-box', [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ]) - test_value('#00f content-box', [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + B + B + _ + _ + _, - _ + _ + _ + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ]) - G = as_pixel(b'\x00\xff\x00\xff') # lime green - test_value('url(pattern.png) padding-box, #0f0', [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + G + G + G + G + G + G + _, - _ + G + r + B + B + B + G + _, - _ + G + B + B + B + B + G + _, - _ + G + B + B + B + B + G + _, - _ + G + B + B + B + B + G + _, - _ + G + G + G + G + G + G + _, - _ + _ + _ + _ + _ + _ + _ + _, - ]) - - -@assert_no_logs -def test_background_size(): - """Test the background-size property.""" - assert_pixels('background_size', 12, 12, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + r + r + B + B + B + B + B + B + _, - _ + _ + _ + r + r + B + B + B + B + B + B + _, - _ + _ + _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_size_auto', 12, 12, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_size_contain', 14, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_size_mixed', 14, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_size_double', 14, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - assert_pixels('background_size_cover', 14, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + r + B + B + B + B + B + B + B + B + B + _, - _ + r + r + r + B + B + B + B + B + B + B + B + B + _, - _ + r + r + r + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - -@assert_no_logs -def test_list_style_image(): - """Test images as list markers.""" - for position, pixels in [ - ('outside', - # ++++++++++++++ ++++

  • horizontal margins: 7px 2px - # ######
  • width: 12 - 7 - 2 = 3px - # -- list marker margin: 0.5em = 2px - # ******** list marker image is 4px wide - [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]), - ('inside', - # ++++++++++++++ ++++
  • horizontal margins: 7px 2px - # ######
  • width: 12 - 7 - 2 = 3px - # ******** list marker image is 4px wide: overflow - [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - ]: - assert_pixels('list_style_image_' + position, 12, 10, pixels, ''' - -
    - ''' % (FONTS, position)) - - assert_pixels('list_style_none', 10, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    • - ''' % (FONTS,)) - - -@assert_no_logs -def test_images(): - """Test images sizes, positions and pixels.""" - centered_image = [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ] - # JPG is lossy... - b = as_pixel(b'\x00\x00\xfe\xff') - blue_image = [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + b + b + b + b + _ + _, - _ + _ + b + b + b + b + _ + _, - _ + _ + b + b + b + b + _ + _, - _ + _ + b + b + b + b + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ] - no_image = [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ] - for filename, image in [ - ('pattern.svg', centered_image), - ('pattern.png', centered_image), - ('pattern.palette.png', centered_image), - ('pattern.gif', centered_image), - ('blue.jpg', blue_image)]: - assert_pixels('inline_image_' + filename, 8, 8, image, ''' - -
      - ''' % filename) - assert_pixels('block_image', 8, 8, centered_image, ''' - -
      - ''') - with capture_logs() as logs: - assert_pixels('image_not_found', 8, 8, no_image, ''' - -
      - ''') - assert len(logs) == 1 - assert 'ERROR: Failed to load image' in logs[0] - assert 'inexistent1.png' in logs[0] - assert_pixels('image_no_src', 8, 8, no_image, ''' - -
      - ''') - with capture_logs() as logs: - assert_same_rendering(200, 30, [ - (name, ''' - -
      %s
      - ''' % html) - for name, html in [ - ('image_alt_text_reference', 'Hello, world!'), - ('image_alt_text_not_found', - 'Hello, world!'), - ('image_alt_text_no_src', - 'Hello, world!'), - ('image_svg_no_intrinsic_size', - '''Hello, world!'''), - ] - ]) - assert len(logs) == 1 - assert 'ERROR: Failed to load image' in logs[0] - assert 'inexistent2.png' in logs[0] - - assert_pixels('image_0x1', 8, 8, no_image, ''' - -
      not shown
      - ''') - assert_pixels('image_1x0', 8, 8, no_image, ''' - -
      not shown
      - ''') - assert_pixels('image_0x0', 8, 8, no_image, ''' - -
      not shown
      - ''') - - page_break = [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ] - assert_pixels('image_page_break', 8, 3 * 8, page_break, ''' - -
      -
      - ''') - - # Regression test: padding used to be ignored on images - assert_pixels('image_with_padding', 8, 8, centered_image, ''' - -
      - -
      - ''') - - # Regression test: this used to cause an exception - assert_pixels('image_in_inline_block', 8, 8, centered_image, ''' - -
      -

      -
      - ''') - - # The same image is used in a repeating background, - # then in a non-repating . - # If Pattern objects are shared carelessly, the image will be repeated. - assert_pixels('image_shared_pattern', 12, 12, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + b + b + b + b + b + b + b + b + _ + _, - _ + _ + b + b + b + b + b + b + b + b + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + b + b + b + b + _ + _ + _ + _ + _ + _, - _ + _ + b + b + b + b + _ + _ + _ + _ + _ + _, - _ + _ + b + b + b + b + _ + _ + _ + _ + _ + _, - _ + _ + b + b + b + b + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
      - - ''') - - -def test_image_resolution(): - assert_same_rendering(20, 20, [ - ('image_resolution_ref', ''' - -
      -
      - '''), - ('image_resolution_img', ''' - -
      -
      - '''), - ('image_resolution_content', ''' - -
      - '''), - ('image_resolution_background', ''' - -
      - '''), - ]) - - -@assert_no_logs -def test_visibility(): - source = ''' - -
      - - -
      - ''' - assert_pixels('visibility_reference', 12, 7, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + B + B + B + _ + r + B + B + B + _ + _, - _ + B + B + B + B + _ + B + B + B + B + _ + _, - _ + B + B + B + B + _ + B + B + B + B + _ + _, - _ + B + B + B + B + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], source % {'extra_css': ''}) - - assert_pixels('visibility_hidden', 12, 7, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], source % {'extra_css': 'div { visibility: hidden }'}) - - assert_pixels('visibility_mixed', 12, 7, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], source % {'extra_css': '''div { visibility: hidden } - span { visibility: visible } '''}) - - -@assert_no_logs -@requires('cairo', (1, 12, 0)) -def test_tables(): - # TODO: refactor colspan/rowspan into CSS: - # td, th { column-span: attr(colspan integer) } - HTML_HANDLERS['x-td'] = HTML_HANDLERS['td'] - HTML_HANDLERS['x-th'] = HTML_HANDLERS['th'] - - source = ''' - - - - - - - - - - - - - - - - - - - - - - - - ''' - # rgba(255, 0, 0, 0.5) above #fff - r = as_pixel(b'\xff\x7f\x7f\xff') - # r above r above #fff - R = as_pixel(b'\xff\x3f\x3f\xff') - # rgba(0, 255, 0, 0.5) above #fff - g = as_pixel(b'\x7f\xff\x7f\xff') - # r above B above #fff. - b = as_pixel(b'\x80\x00\x7f\xff') - # r above r above B above #fff. - p = as_pixel(b'\xc0\x00\x3f\xff') - - assert_pixels('table_borders', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+_+_+_+_+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+r+r+r+r+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+R+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+R+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+R+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+R+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border-color: #00f; table-layout: fixed } - x-td { border-color: rgba(255, 0, 0, 0.5) } - '''}) - - assert_pixels('table_collapsed_borders', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+r+r+r+r+r+_+_+_+_+r+r+r+r+r+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+r+r+r+r+r+r+r+r+r+r+r+r+r+r+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border: 2px solid #00f; table-layout: fixed; - border-collapse: collapse } - x-td { border-color: #ff7f7f } - '''}) - - assert_pixels('table_collapsed_borders_paged', 28, 52, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+r+r+r+r+r+_+_+_+_+r+r+r+r+r+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+r+r+r+r+r+r+r+r+r+r+r+r+r+r+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa - _+g+_+B+B+r+r+r+r+r+r+r+r+r+r+r+r+r+r+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa - _+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border: solid #00f; border-width: 8px 2px; - table-layout: fixed; border-collapse: collapse } - x-td { border-color: #ff7f7f } - @page { size: 28px 26px; margin: 1px; - border: 1px solid rgba(0, 255, 0, 0.5); } - '''}) - - assert_pixels('table_td_backgrounds', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+R+R+R+R+R+R+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border-color: #00f; table-layout: fixed } - x-td { background: rgba(255, 0, 0, 0.5) } - '''}) - - assert_pixels('table_row_backgrounds', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border-color: #00f; table-layout: fixed } - x-tbody { background: rgba(0, 0, 255, 1) } - x-tr { background: rgba(255, 0, 0, 0.5) } - '''}) - - assert_pixels('table_column_backgrounds', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border-color: #00f; table-layout: fixed } - x-colgroup { background: rgba(0, 0, 255, 1) } - x-col { background: rgba(255, 0, 0, 0.5) } - '''}) - - assert_pixels('table_borders_and_row_backgrounds', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+b+B+B+B+B+b+_+b+b+b+b+b+b+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+b+B+B+B+B+b+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+p+b+b+b+b+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+r+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border-color: #00f; table-layout: fixed } - x-tr:first-child { background: blue } - x-td { border-color: rgba(255, 0, 0, 0.5) } - '''}) - - assert_pixels('table_borders_and_column_backgrounds', 28, 28, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+r+_+_+_+_+r+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+b+b+b+b+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], source % {'extra_css': ''' - x-table { border-color: #00f; table-layout: fixed } - x-col:first-child { background: blue } - x-td { border-color: rgba(255, 0, 0, 0.5) } - '''}) - - r = as_pixel(b'\xff\x00\x00\xff') - assert_pixels('collapsed_border_thead', 22, 36, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], ''' - -
  • - - - - - ''') - - assert_pixels('collapsed_border_tfoot', 22, 36, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], ''' - -
    - - - - - ''') - - # Regression test for inline table with collapsed border and alignment - # rendering borders incorrectly - # https://github.com/Kozea/WeasyPrint/issues/82 - assert_pixels('inline_text_align', 20, 10, [ - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+r+r+r+r+r+r+r+r+r+r+r+_, # noqa - _+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+r+_, # noqa - _+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+r+_, # noqa - _+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+r+_, # noqa - _+_+_+_+_+_+_+_+r+r+r+r+r+r+r+r+r+r+r+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - _+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa - ], ''' - -
    - - ''') - - -@assert_no_logs -def test_before_after(): - assert_same_rendering(300, 30, [ - ('pseudo_before', ''' - -

    some content

    - '''), - ('pseudo_before_reference', ''' - -

    [some url] some content

    - ''') - ], tolerance=10) - - assert_same_rendering(500, 30, [ - ('pseudo_quotes', ''' - -

    Lorem ipsum dolor sit amet

    - '''), - ('pseudo_quotes_reference', ''' - -

    « Lorem ipsum - “ dolor ” - sit amet »

    - ''') - ], tolerance=10) - - assert_same_rendering(100, 30, [ - ('pseudo_url', ''' - -

    c

    - '''), - ('pseudo_url_reference', ''' - -

    aMissing imagebc

    - ''') - ], tolerance=10) - - -@assert_no_logs -def test_borders(margin='10px', prop='border'): - """Test the rendering of borders""" - source = ''' - - - ''' - - # Do not test the exact rendering of earch border style but at least - # check that they do not do the same. - assert_different_renderings(140, 110, [ - ('%s_%s' % (prop, border_style), source % (margin, prop, border_style)) - for border_style in [ - 'none', 'solid', 'dashed', 'dotted', 'double', - 'inset', 'outset', 'groove', 'ridge', - ] - ]) - - css_margin = margin - width = 140 - height = 110 - margin = 10 - border = 10 - solid_pixels = [[_] * width for y in range(height)] - for x in range(margin, width - margin): - for y in itertools.chain( - range(margin, margin + border), - range(height - margin - border, height - margin)): - solid_pixels[y][x] = B - for y in range(margin, height - margin): - for x in itertools.chain( - range(margin, margin + border), - range(width - margin - border, width - margin)): - solid_pixels[y][x] = B - solid_pixels = [b''.join(line) for line in solid_pixels] - assert_pixels( - prop + '_solid', 140, 110, solid_pixels, - source % (css_margin, prop, 'solid') - ) - - -def test_outlines(): - return test_borders(margin='20px', prop='outline') - - -@assert_no_logs -def test_small_borders(): - # Regression test for ZeroDivisionError on dashed or dotted borders - # smaller than a dash/dot. - # https://github.com/Kozea/WeasyPrint/issues/49 - html = ''' - - ''' - for style in ['none', 'solid', 'dashed', 'dotted']: - HTML(string=html % style).write_image_surface() - - # Regression test for ZeroDivisionError on dashed or dotted borders - # smaller than a dash/dot. - # https://github.com/Kozea/WeasyPrint/issues/146 - html = ''' - - ''' - for style in ['none', 'solid', 'dashed', 'dotted']: - HTML(string=html % style).write_image_surface() - - -@assert_no_logs -def test_margin_boxes(): - """Test the rendering of margin boxes""" - _ = as_pixel(b'\xff\xff\xff\xff') # white - R = as_pixel(b'\xff\x00\x00\xff') # red - G = as_pixel(b'\x00\xff\x00\xff') # green - B = as_pixel(b'\x00\x00\xff\xff') # blue - g = as_pixel(b'\x00\x80\x00\xff') # half green - b = as_pixel(b'\x00\x00\x80\xff') # half blue - assert_pixels('margin_boxes', 15, 15, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + G + G + G + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + G + G + G + _ + _ + _ + _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + R + R + R + R + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + R + R + R + R + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + R + R + R + R + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + R + R + R + R + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + b + b + b + _ + _ + _ + _ + _ + _ + g + g + g + g + _, - _ + b + b + b + _ + _ + _ + _ + _ + _ + g + g + g + g + _, - _ + b + b + b + _ + _ + _ + _ + _ + _ + g + g + g + g + _, - _ + b + b + b + _ + _ + _ + _ + _ + _ + g + g + g + g + _, - _ + b + b + b + _ + _ + _ + _ + _ + _ + g + g + g + g + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - - - ''') - - -@assert_no_logs -def test_unicode(): - """Test non-ASCII filenames (URLs)""" - text = 'I løvë Unicode' - style = ''' - @page { - background: #fff; - size: 200px 50px; - } - p { color: blue } - ''' - _doc, expected_lines = html_to_pixels('unicode_reference', 200, 50, ''' - -

    {1}

    - '''.format(style, text)) - - temp = tempfile.mkdtemp(prefix=text + '-') - try: - stylesheet = os.path.join(temp, 'style.css') - image = os.path.join(temp, 'pattern.png') - html = os.path.join(temp, 'doc.html') - with open(stylesheet, 'wb') as fd: - fd.write(style.encode('utf8')) - with open(resource_filename('pattern.png'), 'rb') as fd: - image_content = fd.read() - with open(image, 'wb') as fd: - fd.write(image_content) - with open(html, 'wb') as fd: - html_content = ''' - -

    {2}

    - '''.format( - ensure_url(stylesheet), ensure_url(image), text - ) - fd.write(html_content.encode('utf8')) - - # TODO: change this back to actually read from a file - document = FakeHTML(html, encoding='utf8') - lines = document_to_pixels(document, 'unicode', 200, 50) - assert_pixels_equal('unicode', 200, 50, lines, expected_lines) - finally: - shutil.rmtree(temp) - - -@assert_no_logs -def test_overflow(): - """Test the overflow property.""" - # See test_images - assert_pixels('inline_image_overflow', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - # is only 1px high, but its overflow is propageted to the viewport - # ie. the padding edge of the page box. - assert_pixels('inline_image_viewport_overflow', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - # Assert that the border is not clipped by overflow: hidden - assert_pixels('border_box_overflow', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + _ + _ + B + _ + _, - _ + _ + B + _ + _ + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - -@assert_no_logs -@requires('cairo', (1, 12, 0)) -def test_clip(): - """Test the clip property.""" - num = [0] - - def clip(css, pixels): - num[0] += 1 - name = 'background_repeat_clipped_%s' % num[0] - assert_pixels(name, 14, 16, pixels, ''' - -
    - ''' % (css,)) - - g = as_pixel(b'\x00\x80\x00\xff') # green - clip('5px, 5px, 9px, auto', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + r + B + g + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + B + g + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + B + g + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + B + g + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - clip('5px, 5px, auto, 10px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + r + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + r + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + g + g + g + g + g + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - clip('5px, auto, 9px, 10px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + g + r + B + B + B + r + B + B + B + r + _ + _ + _, - _ + g + B + B + B + B + B + B + B + B + B + _ + _ + _, - _ + g + B + B + B + B + B + B + B + B + B + _ + _ + _, - _ + g + B + B + B + B + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - clip('auto, 5px, 9px, 10px', [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + g + g + g + g + g + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + r + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + r + B + B + B + r + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + B + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ]) - - -@assert_no_logs -def test_opacity(): - """Test the opacity property.""" - template = ''' - - %s - ''' - assert_same_rendering(60, 60, [ - ('opacity_0_reference', template % ''' -
    - '''), - ('opacity_0', template % ''' -
    -
    - '''), - ]) - assert_same_rendering(60, 60, [ - ('opacity_color_reference', template % ''' -
    - '''), - ('opacity_color', template % ''' -
    - '''), - ]) - assert_same_rendering(60, 60, [ - ('opacity_multiplied_reference', template % ''' -
    - '''), - ('opacity_multiplied', template % ''' -
    - '''), - ('opacity_multiplied_2', template % ''' -
    -
    -
    - '''), # 0.9 * 0.666666 == 0.6 - ]) - - -@assert_no_logs -def test_current_color(): - """Test inheritance of the currentColor keyword.""" - G = b'\x00\xff\x00\xff' # lime (light green) - assert_pixels('background_current_color', 2, 2, [G + G, G + G], ''' - - - ''') - assert_pixels('border_current_color', 2, 2, [G + G, G + G], ''' - - - ''') - assert_pixels('outline_current_color', 2, 2, [G + G, G + G], ''' - - - ''') - assert_pixels('border_collapse_current_color', 2, 2, [G + G, G + G], ''' - -
    - ''') - - -@assert_no_logs -def test_2d_transform(): - """Test 2D transformations.""" - assert_pixels('image_rotate90', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + r + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_translateX_rotate90', 12, 12, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + r + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - # A translateX after the rotation is actually a translateY - assert_pixels('image_rotate90_translateX', 12, 12, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + r + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - assert_pixels('nested_rotate90_translateX', 12, 12, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + r + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_reflection', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + B + B + B + r + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_translate', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + r + B + B + B + _, - _ + _ + _ + B + B + B + B + _, - _ + _ + _ + B + B + B + B + _, - _ + _ + _ + B + B + B + B + _, - ], ''' - -
    - ''') - - assert_pixels('image_translate_percentage', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + r + B + B + B + _, - _ + _ + _ + B + B + B + B + _, - _ + _ + _ + B + B + B + B + _, - _ + _ + _ + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_translateX', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + r + B + B, - _ + _ + _ + _ + _ + B + B + B, - _ + _ + _ + _ + _ + B + B + B, - _ + _ + _ + _ + _ + B + B + B, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_translateY', 8, 8, [ - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + B + B + B + B + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_scale', 10, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_scale12', 10, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_scaleY', 10, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _, - _ + _ + r + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + B + B + B + B + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - assert_pixels('image_scaleX', 10, 10, [ - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + r + r + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + B + B + B + B + B + B + B + B + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - _ + _ + _ + _ + _ + _ + _ + _ + _ + _, - ], ''' - -
    - ''') - - -@assert_no_logs -@requires('cairo', (1, 12, 0)) -def test_acid2(): - """A local version of http://acid2.acidtests.org/""" - def render(filename): - return HTML(resource_filename(filename)).render(enable_hinting=True) - - with capture_logs(): - # This is a copy of http://www.webstandards.org/files/acid2/test.html - document = render('acid2-test.html') - intro_page, test_page = document.pages - # Ignore the intro page: it is not in the reference - test_image, width, height = document.copy( - [test_page]).write_image_surface() - - # This is a copy of http://www.webstandards.org/files/acid2/reference.html - ref_image, ref_width, ref_height = render( - 'acid2-reference.html').write_image_surface() - - assert (width, height) == (ref_width, ref_height) - assert_pixels_equal( - 'acid2', width, height, image_to_pixels(test_image, width, height), - image_to_pixels(ref_image, width, height), tolerance=2) - - -@assert_no_logs -@requires('cairo', (1, 14, 0)) -def test_linear_gradients(): - assert_pixels('linear_gradient', 5, 9, [ - _ + _ + _ + _ + _, - _ + _ + _ + _ + _, - _ + _ + _ + _ + _, - B + B + B + B + B, - B + B + B + B + B, - r + r + r + r + r, - r + r + r + r + r, - r + r + r + r + r, - r + r + r + r + r, - ], ''' -
    - - - - -
    - ''') - - assert_pixels('dotted', 5, 3, [ - b + _ + r + _ + b, - b + _ + _ + _ + b, - b + _ + r + _ + b, - ], ''' - -
    - - - - - - -
    - ''') diff --git a/weasyprint/tests/test_draw/__init__.py b/weasyprint/tests/test_draw/__init__.py new file mode 100644 index 00000000..6c9454e6 --- /dev/null +++ b/weasyprint/tests/test_draw/__init__.py @@ -0,0 +1,152 @@ +""" + weasyprint.tests.test_draw + -------------------------- + + Test the final, drawn results and compare PNG images pixel per pixel. + + :copyright: Copyright 2011-2018 Simon Sapin and contributors, see AUTHORS. + :license: BSD, see LICENSE for details. + +""" + +import os +import sys + +import cairocffi as cairo + +from ..testing_utils import FakeHTML, resource_filename + + +# RGBA to native-endian ARGB +as_pixel = ( + lambda x: x[:-1][::-1] + x[-1:] + if sys.byteorder == 'little' else + lambda x: x[-1:] + x[:-1]) + +_ = as_pixel(b'\xff\xff\xff\xff') # white +R = as_pixel(b'\xff\x00\x00\xff') # red +B = as_pixel(b'\x00\x00\xff\xff') # blue +G = as_pixel(b'\x00\xff\x00\xff') # lime green +V = as_pixel(b'\xBF\x00\x40\xff') # Average of 1*B and 3*r. +S = as_pixel(b'\xff\x3f\x3f\xff') # r above r above #fff +r = as_pixel(b'\xff\x00\x00\xff') # red +g = as_pixel(b'\x00\x80\x00\xff') # half green +b = as_pixel(b'\x00\x00\x80\xff') # half blue +v = as_pixel(b'\x80\x00\x80\xff') # Average of B and r. +a = as_pixel(b'\x00\x00\xfe\xff') # JPG is lossy... +p = as_pixel(b'\xc0\x00\x3f\xff') # r above r above B above #fff. + + +def assert_pixels(name, expected_width, expected_height, expected_pixels, + html): + """Helper testing the size of the image and the pixels values.""" + assert len(expected_pixels) == expected_height + assert len(expected_pixels[0]) == expected_width * 4 + expected_raw = b''.join(expected_pixels) + _doc, pixels = html_to_pixels(name, expected_width, expected_height, html) + assert_pixels_equal( + name, expected_width, expected_height, pixels, expected_raw) + + +def assert_same_rendering(expected_width, expected_height, documents, + tolerance=0): + """Render HTML documents to PNG and check that they render the same. + + Each document is passed as a (name, html_source) tuple. + + """ + pixels_list = [] + + for name, html in documents: + _doc, pixels = html_to_pixels( + name, expected_width, expected_height, html) + pixels_list.append((name, pixels)) + + _name, reference = pixels_list[0] + for name, pixels in pixels_list[1:]: + assert_pixels_equal(name, expected_width, expected_height, + reference, pixels, tolerance) + + +def assert_different_renderings(expected_width, expected_height, documents): + """Render HTML documents to PNG and check that they don't render the same. + + Each document is passed as a (name, html_source) tuple. + + """ + pixels_list = [] + + for name, html in documents: + _doc, pixels = html_to_pixels( + name, expected_width, expected_height, html) + pixels_list.append((name, pixels)) + + for i, (name_1, pixels_1) in enumerate(pixels_list): + for name_2, pixels_2 in pixels_list[i + 1:]: + if pixels_1 == pixels_2: # pragma: no cover + write_png(name_1, pixels_1, expected_width, expected_height) + # Same as "assert pixels_1 != pixels_2" but the output of + # the assert hook would be gigantic and useless. + assert False, '%s and %s are the same' % (name_1, name_2) + + +def write_png(basename, pixels, width, height): # pragma: no cover + """Take a pixel matrix and write a PNG file.""" + directory = os.path.join(os.path.dirname(__file__), 'results') + if not os.path.isdir(directory): + os.mkdir(directory) + filename = os.path.join(directory, basename + '.png') + cairo.ImageSurface( + cairo.FORMAT_ARGB32, width, height, + data=bytearray(pixels), stride=width * 4 + ).write_to_png(filename) + + +def html_to_pixels(name, expected_width, expected_height, html): + """Render an HTML document to PNG, checks its size and return pixel data. + + Also return the document to aid debugging. + + """ + document = FakeHTML( + string=html, + # Dummy filename, but in the right directory. + base_url=resource_filename('')) + pixels = document_to_pixels( + document, name, expected_width, expected_height) + return document, pixels + + +def document_to_pixels(document, name, expected_width, expected_height): + """Render an HTML document to PNG, check its size and return pixel data.""" + surface = document.write_image_surface() + return image_to_pixels(surface, expected_width, expected_height) + + +def image_to_pixels(surface, width, height): + assert (surface.get_width(), surface.get_height()) == (width, height) + # RGB24 is actually the same as ARGB32, with A unused. + assert surface.get_format() in (cairo.FORMAT_ARGB32, cairo.FORMAT_RGB24) + pixels = surface.get_data()[:] + assert len(pixels) == width * height * 4 + return pixels + + +def assert_pixels_equal(name, width, height, raw, expected_raw, tolerance=0): + """Take 2 matrices of pixels and assert that they are the same.""" + if raw != expected_raw: # pragma: no cover + for i, (value, expected) in enumerate(zip(raw, expected_raw)): + if abs(value - expected) > tolerance: + write_png(name, raw, width, height) + write_png(name + '.expected', expected_raw, + width, height) + pixel_n = i // 4 + x = pixel_n // width + y = pixel_n % width + i % 4 + pixel = tuple(list(raw[i:i + 4])) + expected_pixel = tuple(list( + expected_raw[i:i + 4])) + assert 0, ( + 'Pixel (%i, %i) in %s: expected rgba%s, got rgba%s' + % (x, y, name, expected_pixel, pixel)) diff --git a/weasyprint/tests/test_draw/test_draw.py b/weasyprint/tests/test_draw/test_draw.py new file mode 100644 index 00000000..814b8953 --- /dev/null +++ b/weasyprint/tests/test_draw/test_draw.py @@ -0,0 +1,2393 @@ +import itertools +import os.path +import shutil +import tempfile + +import pytest + +from . import ( + B, G, R, V, _, a, assert_different_renderings, assert_pixels, + assert_pixels_equal, assert_same_rendering, b, document_to_pixels, g, + html_to_pixels, image_to_pixels, r, v) +from ... import HTML +from ...urls import ensure_url +from ..testing_utils import ( + FONTS, FakeHTML, assert_no_logs, capture_logs, requires, resource_filename) + + +@assert_no_logs +@pytest.mark.parametrize( + 'name, expected_width, expected_height, expected_pixels, html', ( + ('all_blue', 10, 10, (10 * [10 * B]), ''' + + '''), + ('blocks', 10, 10, [ + r + r + r + r + r + r + r + r + r + r, + r + r + r + r + r + r + r + r + r + r, + r + r + B + B + B + B + B + B + r + r, + r + r + B + B + B + B + B + B + r + r, + r + r + B + B + B + B + B + B + r + r, + r + r + B + B + B + B + B + B + r + r, + r + r + B + B + B + B + B + B + r + r, + r + r + r + r + r + r + r + r + r + r, + r + r + r + r + r + r + r + r + r + r, + r + r + r + r + r + r + r + r + r + r, + ], ''' + + '''), + )) +def test_canvas_background(name, expected_width, expected_height, + expected_pixels, html): + assert_pixels(name, expected_width, expected_height, expected_pixels, html) + + +@assert_no_logs +@pytest.mark.parametrize('name, css, pixels', ( + ('repeat', 'url(pattern.png)', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('repeat_x', 'url(pattern.png) repeat-x', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + r + B + B + B + r + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('repeat_y', 'url(pattern.png) repeat-y', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + + ('left_top', 'url(pattern.png) no-repeat 0 0%', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('center_top', 'url(pattern.png) no-repeat 50% 0px', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('right_top', 'url(pattern.png) no-repeat 6px top', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('bottom_6_right_0', 'url(pattern.png) no-repeat bottom 6px right 0', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('left_center', 'url(pattern.png) no-repeat left center', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('center_left', 'url(pattern.png) no-repeat center left', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('center_center', 'url(pattern.png) no-repeat 3px 3px', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('right_center', 'url(pattern.png) no-repeat 100% 50%', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + + ('left_bottom', 'url(pattern.png) no-repeat 0% bottom', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('center_bottom', 'url(pattern.png) no-repeat center 6px', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('bottom_center', 'url(pattern.png) no-repeat bottom center', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('right_bottom', 'url(pattern.png) no-repeat 6px 100%', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + + ('repeat_x_1px_2px', 'url(pattern.png) repeat-x 1px 2px', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + r + B + B + B + r + B + B + B + r + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + B + B + B + B + B + B + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('repeat_y_local_2px_1px', 'url(pattern.png) repeat-y local 2px 1px', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + + ('fixed', 'url(pattern.png) no-repeat fixed', [ + # The image is actually here: + ####### + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # + _ + _ + B + B + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # + _ + _ + B + B + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, # + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('fixed_right', 'url(pattern.png) no-repeat fixed right 3px', [ + # x x x x + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + r + B + _ + _, # x + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _, # x + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _, # x + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _, # x + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('fixed_center_center', 'url(pattern.png)no-repeat fixed 50%center', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('multi_under', '''url(pattern.png) no-repeat, + url(pattern.png) no-repeat 2px 1px''', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('multi_over', '''url(pattern.png) no-repeat 2px 1px, + url(pattern.png) no-repeat''', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + r + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), +)) +def test_background_image(name, css, pixels): + # pattern.png looks like this: + + # r + B + B + B, + # B + B + B + B, + # B + B + B + B, + # B + B + B + B, + + assert_pixels('background_' + name, 14, 16, pixels, ''' + + +

     ''' % css) + + +@assert_no_logs +def test_background_image_zero_size_background(): + # Regression test for https://github.com/Kozea/WeasyPrint/issues/217 + assert_pixels('zero_size_background', 10, 10, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_origin(): + """Test the background-origin property.""" + def test_value(value, pixels, css=None): + assert_pixels('background_origin_' + value, 12, 12, pixels, ''' + + ''' % (css or value,)) + + test_value('border-box', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]) + test_value('padding-box', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + r + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]) + test_value('content-box', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + r + B + B + B + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, + _ + _ + _ + _ + _ + B + B + B + B + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]) + + test_value('border-box_clip', [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + r + B + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + B + B + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], css='border-box; background-clip: content-box') + + +@assert_no_logs +def test_background_repeat_space_1(): + assert_pixels('background_repeat_space', 12, 16, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + _ + _ + r + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + _ + _ + r + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + _ + _ + r + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_repeat_space_2(): + assert_pixels('background_repeat_space', 12, 14, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + _ + _ + r + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + r + B + B + B + _ + _ + r + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + r + B + B + B + _ + _ + r + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + B + B + B + B + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_repeat_space_3(): + assert_pixels('background_repeat_space', 12, 13, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + r + B + B + B + r + B + _, + _ + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + r + B + B + B + r + B + _, + _ + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_repeat_round_1(): + assert_pixels('background_repeat_round', 10, 14, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_repeat_round_2(): + assert_pixels('background_repeat_round', 10, 18, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_repeat_round_3(): + assert_pixels('background_repeat_round', 10, 14, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + r + r + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +def test_background_repeat_round_4(): + assert_pixels('background_repeat_round', 10, 14, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + B + B + B + r + B + B + B + _, + _ + r + B + B + B + r + B + B + B + _, + _ + r + B + B + B + r + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + ''') + + +@assert_no_logs +@pytest.mark.parametrize('value, pixels', ( + ('#00f border-box', [ + _ + _ + _ + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('#00f padding-box', [ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _, + _ + _ + B + B + B + B + _ + _, + _ + _ + B + B + B + B + _ + _, + _ + _ + B + B + B + B + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('#00f content-box', [ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + B + B + _ + _ + _, + _ + _ + _ + B + B + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('url(pattern.png) padding-box, #0f0', [ + _ + _ + _ + _ + _ + _ + _ + _, + _ + G + G + G + G + G + G + _, + _ + G + r + B + B + B + G + _, + _ + G + B + B + B + B + G + _, + _ + G + B + B + B + B + G + _, + _ + G + B + B + B + B + G + _, + _ + G + G + G + G + G + G + _, + _ + _ + _ + _ + _ + _ + _ + _, + ]), +)) +def test_background_clip(value, pixels): + assert_pixels('background_clip_' + value, 8, 8, pixels, ''' + + ''' % value) + + +@assert_no_logs +@pytest.mark.parametrize( + 'name, expected_width, expected_height, expected_pixels, html', ( + ('background_size', 12, 12, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + r + r + B + B + B + B + B + B + _, + _ + _ + _ + r + r + B + B + B + B + B + B + _, + _ + _ + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + '''), + ('background_size_auto', 12, 12, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + '''), + ('background_size_contain', 14, 10, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + '''), + + ('background_size_mixed', 14, 10, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + '''), + ('background_size_double', 14, 10, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + B + B + B + B + B + B + B + B + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + '''), + ('background_size_cover', 14, 10, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + r + r + r + B + B + B + B + B + B + B + B + B + _, + _ + r + r + r + B + B + B + B + B + B + B + B + B + _, + _ + r + r + r + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + B + B + _, + _ + B + B + B + B + B + B + B + B + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + + '''), + ) +) +def test_background_size(name, expected_width, expected_height, + expected_pixels, html): + assert_pixels( + name, expected_width, expected_height, expected_pixels, html) + + +@assert_no_logs +@pytest.mark.parametrize('position, pixels', ( + ('outside', + # ++++++++++++++ ++++

  • horizontal margins: 7px 2px + # ######
  • width: 12 - 7 - 2 = 3px + # -- list marker margin: 0.5em = 2px + # ******** list marker image is 4px wide + [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + r + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + B + B + B + B + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]), + ('inside', + # ++++++++++++++ ++++
  • horizontal margins: 7px 2px + # ######
  • width: 12 - 7 - 2 = 3px + # ******** list marker image is 4px wide: overflow + [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + r + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + B + B + B + B + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ]) +)) +def test_list_style_image(position, pixels): + assert_pixels('list_style_image_' + position, 12, 10, pixels, ''' + +
    ''' % (FONTS, position)) + + +@assert_no_logs +def test_list_style_image_none(): + assert_pixels('list_style_none', 10, 10, [ + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + _ + _ + _ + _ + _ + _ + _ + _ + _ + _, + ], ''' + +