From 8499379dd1762cc5c429f5f6704467ae3ca2ce4e Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Sun, 2 Jun 2019 23:03:19 +0200 Subject: [PATCH] Don't repeat background images when it's not needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now, we only avoid the repetition when we have no-repeat for x and y axes. We could do this when the painting area is smaller than the image and when the position doesn't require a repetition. But… Who cares? Fix #238. There was also a bug in the size of the surface needed to draw images that are not repeated. Before this commit, the repeat size was the painting size * 2 to avoid glitches at the boundaries. But we have to be sure to draw at least the whole image, as the image may be translated before being drawn. The multiplication is not needed as we don't repeat the image anymore. Related to #669. --- weasyprint/draw.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/weasyprint/draw.py b/weasyprint/draw.py index 8da633dac..97a5ccdcc 100644 --- a/weasyprint/draw.py +++ b/weasyprint/draw.py @@ -426,7 +426,6 @@ def draw_table_backgrounds(context, page, table, enable_hinting): def draw_background_image(context, layer, image_rendering): - # Background image if layer.image is None: return @@ -439,20 +438,29 @@ def draw_background_image(context, layer, image_rendering): image_width, image_height = layer.size if repeat_x == 'no-repeat': - repeat_width = painting_width * 2 + # We want at least the whole image_width drawn on sub_surface, but we + # want to be sure it will not be repeated on the painting_width. + repeat_width = max(image_width, painting_width) elif repeat_x in ('repeat', 'round'): + # We repeat the image each image_width. repeat_width = image_width else: assert repeat_x == 'space' n_repeats = math.floor(positioning_width / image_width) if n_repeats >= 2: + # The repeat width is the whole positioning width with one image + # removed, divided by (the number of repeated images - 1). This + # way, we get the width of one image + one space. We ignore + # background-position for this dimension. repeat_width = (positioning_width - image_width) / (n_repeats - 1) - position_x = 0 # Ignore background-position for this dimension + position_x = 0 else: + # We don't repeat the image. repeat_width = image_width + # Comments above apply here too. if repeat_y == 'no-repeat': - repeat_height = painting_height * 2 + repeat_height = max(image_height, painting_height) elif repeat_y in ('repeat', 'round'): repeat_height = image_height else: @@ -461,7 +469,7 @@ def draw_background_image(context, layer, image_rendering): if n_repeats >= 2: repeat_height = ( positioning_height - image_height) / (n_repeats - 1) - position_y = 0 # Ignore background-position for this dimension + position_y = 0 else: repeat_height = image_height @@ -471,7 +479,11 @@ def draw_background_image(context, layer, image_rendering): sub_context.clip() layer.image.draw(sub_context, image_width, image_height, image_rendering) pattern = cairo.SurfacePattern(sub_surface) - pattern.set_extend(cairo.EXTEND_REPEAT) + + if repeat_x == repeat_y == 'no-repeat': + pattern.set_extend(cairo.EXTEND_NONE) + else: + pattern.set_extend(cairo.EXTEND_REPEAT) with stacked(context): if not layer.unbounded: