From 29388af63fcda5c7c4b5830b4fc33a96e71a272a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 16 Dec 2011 14:25:05 +0100 Subject: [PATCH] Move backgroun-position parsing from draw to validation --- weasy/css/validation.py | 26 ++++++++++++----- weasy/css/values.py | 11 ++++++++ weasy/draw.py | 45 +++++++----------------------- weasy/tests/test_css_properties.py | 6 ++-- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/weasy/css/validation.py b/weasy/css/validation.py index 24220f9a..c6188be8 100644 --- a/weasy/css/validation.py +++ b/weasy/css/validation.py @@ -29,7 +29,8 @@ import functools import logging from ..formatting_structure import counters -from .values import get_keyword, get_single_keyword, as_css +from .values import (get_keyword, get_single_keyword, as_css, + make_percentage_value) from .properties import INITIAL_VALUES, NOT_PRINT_MEDIA from . import computed_values @@ -42,6 +43,14 @@ CONTENT_QUOTE_KEYWORDS = { 'no-close-quote': (False, False), } +BACKGROUND_POSITION_PERCENTAGES = { + 'top': make_percentage_value(0), + 'left': make_percentage_value(0), + 'center': make_percentage_value(50), + 'bottom': make_percentage_value(100), + 'right': make_percentage_value(100), +} + LOGGER = logging.getLogger('WEASYPRINT') # yes/no validators for non-shorthand properties @@ -176,25 +185,27 @@ def background_position(values): See http://www.w3.org/TR/CSS21/colors.html#propdef-background-position """ + kw_to_percentage = dict(top=0, left=0, center=50, bottom=100, right=100) if len(values) == 1: + center = BACKGROUND_POSITION_PERCENTAGES['center'] value = values[0] keyword = get_keyword(value) - if keyword in ('left', 'right', 'top', 'bottom', 'center'): - return keyword, 'center' + if keyword in BACKGROUND_POSITION_PERCENTAGES: + return BACKGROUND_POSITION_PERCENTAGES[keyword], center elif is_dimension_or_percentage(value): - return value, 'center' + return value, center elif len(values) == 2: value_1, value_2 = values keyword_1, keyword_2 = map(get_keyword, values) if is_dimension_or_percentage(value_1): if keyword_2 in ('top', 'center', 'bottom'): - return value_1, keyword_2 + return value_1, BACKGROUND_POSITION_PERCENTAGES[keyword_2] elif is_dimension_or_percentage(value_2): return value_1, value_2 elif is_dimension_or_percentage(value_2): if keyword_1 in ('left', 'center', 'right'): - return keyword_1, value_2 + return BACKGROUND_POSITION_PERCENTAGES[keyword_1], value_2 elif ( keyword_1 in ('left', 'center', 'right') and keyword_2 in ('top', 'center', 'bottom') @@ -202,7 +213,8 @@ def background_position(values): keyword_1 in ('top', 'center', 'bottom') and keyword_2 in ('left', 'center', 'right') ): - return keyword_1, keyword_2 + return (BACKGROUND_POSITION_PERCENTAGES[keyword_1], + BACKGROUND_POSITION_PERCENTAGES[keyword_2]) #else: invalid diff --git a/weasy/css/values.py b/weasy/css/values.py index 040c6deb..4f2d5db4 100644 --- a/weasy/css/values.py +++ b/weasy/css/values.py @@ -22,6 +22,9 @@ Utility functions and methods used by various modules in the css package. """ +import collections + + def get_keyword(value): """If ``value`` is a keyword, return its name. @@ -63,3 +66,11 @@ def get_percentage_value(value): def as_css(values): """Return the string reperesentation of the ``values`` list.""" return ' '.join(getattr(value, 'cssText', value) for value in values) + + +FakeValue = collections.namedtuple('FakeValue', ('type', 'value', 'cssText')) + + +def make_percentage_value(value): + """Return an object that ``get_percentage_value()`` will accept.""" + return FakeValue('PERCENTAGE', value, '{}%'.format(value)) diff --git a/weasy/draw.py b/weasy/draw.py index 42f64985..5ae74636 100644 --- a/weasy/draw.py +++ b/weasy/draw.py @@ -177,9 +177,16 @@ def draw_background(document, context, box, clip=True): surface, image_width, image_height = image - bg_position = box.style.background_position - bg_position_x, bg_position_y = absolute_background_position( - bg_position, (bg_width, bg_height), (image_width, image_height)) + bg_position_x, bg_position_y = box.style.background_position + + percentage = get_percentage_value(bg_position_x) + if percentage is not None: + bg_position_x = (bg_width - image_width) * percentage / 100. + + percentage = get_percentage_value(bg_position_y) + if percentage is not None: + bg_position_y = (bg_height - image_height) * percentage / 100. + context.translate(bg_position_x, bg_position_y) bg_repeat = box.style.background_repeat @@ -208,38 +215,6 @@ def draw_background(document, context, box, clip=True): context.paint() -def absolute_background_position(css_values, bg_dimensions, image_dimensions): - """Return the background's ``position_x, position_y`` in pixels. - - http://www.w3.org/TR/CSS21/colors.html#propdef-background-position - - :param css_values: a list of one or two cssutils Value objects. - :param bg_dimensions: ``width, height`` of the background positionning area - :param image_dimensions: ``width, height`` of the background image - - """ - values = list(css_values) - - if len(css_values) == 1: - values.append('center') - else: - assert len(css_values) == 2 - - if values[1] in ('left', 'right') or values[0] in ('top', 'bottom'): - values.reverse() - # Order is now [horizontal, vertical] - - kw_to_percentage = dict(top=0, left=0, center=50, bottom=100, right=100) - - for value, bg_dimension, image_dimension in zip( - values, bg_dimensions, image_dimensions): - percentage = kw_to_percentage.get(value, get_percentage_value(value)) - if percentage is not None: - yield (bg_dimension - image_dimension) * percentage / 100. - else: - yield value - - def get_rectangle_edges(x, y, width, height): """Return the 4 edges of a rectangle as a list. diff --git a/weasy/tests/test_css_properties.py b/weasy/tests/test_css_properties.py index 1acb2e11..6ccfd7e7 100644 --- a/weasy/tests/test_css_properties.py +++ b/weasy/tests/test_css_properties.py @@ -199,7 +199,7 @@ def test_expand_background(): image='none', repeat='repeat', attachment='scroll', - position='top right' ## + position='0% 100%' ## ) assert_background( 'url(bar) #f00 repeat-y center left fixed', @@ -207,7 +207,7 @@ def test_expand_background(): image='bar', ## repeat='repeat-y', ## attachment='fixed', ## - position='center left' ## + position='50% 0%' ## ) assert_background( '#00f 10% 200px', @@ -223,7 +223,7 @@ def test_expand_background(): image='none', repeat='repeat', attachment='fixed', ## - position='right 78px' ## + position='100% 78px' ## )