1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-10-05 00:21:15 +03:00

Move backgroun-position parsing from draw to validation

This commit is contained in:
Simon Sapin 2011-12-16 14:25:05 +01:00
parent 7047e7de9b
commit 29388af63f
4 changed files with 43 additions and 45 deletions

View File

@ -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

View File

@ -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))

View File

@ -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.

View File

@ -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' ##
)