Skip to content

Commit

Permalink
Avoid changing draw.py and boxes.py
Browse files Browse the repository at this point in the history
  • Loading branch information
kygoh committed Feb 13, 2024
1 parent f332f4d commit a7f355c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 49 deletions.
3 changes: 0 additions & 3 deletions tests/draw/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,6 @@ def test_border_collapse_bidi_border_left(assert_pixels):
''')


@pytest.mark.xfail
@assert_no_logs
def test_border_collapse_bidi_border_top(assert_pixels):
assert_pixels('''
Expand Down Expand Up @@ -1827,7 +1826,6 @@ def test_border_collapse_bidi_border_top(assert_pixels):
''')


@pytest.mark.xfail
@assert_no_logs
def test_border_collapse_bidi_border_bottom(assert_pixels):
assert_pixels('''
Expand Down Expand Up @@ -1937,7 +1935,6 @@ def test_border_collapse_bidi_border_bottom(assert_pixels):
''')


@pytest.mark.xfail
@assert_no_logs
def test_border_collapse_bidi_broad_border(assert_pixels):
assert_pixels('''
Expand Down
14 changes: 11 additions & 3 deletions weasyprint/draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,11 @@ def draw_table(stream, table):
draw_background(stream, row_group.background)
for row in row_group.children:
draw_background(stream, row.background)
for cell in row.children:
if table.style['direction'] == 'rtl':
cells = reversed(row.children)
else:
cells = row.children
for cell in cells:
if (table.style['border_collapse'] == 'collapse' or
cell.style['empty_cells'] == 'show' or
not cell.empty):
Expand Down Expand Up @@ -951,11 +955,15 @@ def add_horizontal(x, y):
score, style, width, color, 'top',
(pos_x1, pos_y, pos_x2 - pos_x1, 0)))

for x in range(grid_width):
if table.style['direction'] == 'rtl':
grid_width_range = range(grid_width - 1, -1, -1)
else:
grid_width_range = range(grid_width)
for x in grid_width_range:
add_horizontal(x, 0)
for y in range(grid_height):
add_vertical(0, y)
for x in range(grid_width):
for x in grid_width_range:
add_vertical(x + 1, y)
add_horizontal(x, y + 1)

Expand Down
14 changes: 11 additions & 3 deletions weasyprint/layout/float.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,17 @@ def avoid_collisions(context, box, containing_block, outer=True):
if shape.style['float'] == 'right']

# Set the default maximum bounds
max_left_bound = containing_block.content_box_x()
max_right_bound = \
containing_block.content_box_x() + containing_block.width
rtl = containing_block.style['direction'] == 'rtl'
if isinstance(containing_block, boxes.TableCellBox) and rtl:
cb = containing_block
cb_x = cb.position_x + cb.margin_right + cb.padding_right + \
cb.border_right_width
max_left_bound = cb_x
max_right_bound = cb_x + containing_block.width
else:
max_left_bound = containing_block.content_box_x()
max_right_bound = \
containing_block.content_box_x() + containing_block.width

if not outer:
max_left_bound += box.margin_left
Expand Down
85 changes: 45 additions & 40 deletions weasyprint/layout/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,24 @@ def table_layout(context, table, bottom_space, skip_stack, containing_block,
border_spacing_x, border_spacing_y = table.style['border_spacing']

column_positions = table.column_positions = []
rows_left_x = table.content_box_x() + border_spacing_x

if table.style['direction'] == 'rtl':
content_box_x = table.position_x + table.margin_right + \
table.padding_right + table.border_right_width
else:
content_box_x = table.content_box_x()

rows_left_x = content_box_x + border_spacing_x
if table.style['direction'] == 'ltr':
position_x = table.content_box_x()
position_x = content_box_x
rows_x = position_x + border_spacing_x
for width in column_widths:
position_x += border_spacing_x
column_positions.append(position_x)
position_x += width
rows_width = position_x - rows_x
else:
position_x = table.content_box_x() + table.width
position_x = content_box_x + table.width
rows_x = position_x - border_spacing_x
for width in column_widths:
position_x -= border_spacing_x
Expand Down Expand Up @@ -1026,20 +1033,20 @@ def set_one_border(border_grid, box_style, side, grid_x, grid_y):
if previous_score < score:
border_grid[grid_y][grid_x] = (score, (style, width, color))

def set_borders(box, x, y, w, h, ltr=True):
def set_borders(box, x, y, w, h, rtl):
style = box.style
if ltr:
start, end = 'left', 'right'
else:
if rtl:
start, end = 'right', 'left'
else:
start, end = 'left', 'right'
for yy in range(y, y + h):
set_one_border(vertical_borders, style, start, x, yy)
set_one_border(vertical_borders, style, end, x + w, yy)
for xx in range(x, x + w):
set_one_border(horizontal_borders, style, 'top', xx, y)
set_one_border(horizontal_borders, style, 'bottom', xx, y + h)

ltr = table.style['direction'] == 'ltr'
rtl = table.style['direction'] == 'rtl'
# The order is important here:
# "A style set on a cell wins over one on a row, which wins over a
# row group, column, column group and, lastly, table"
Expand All @@ -1049,7 +1056,8 @@ def set_borders(box, x, y, w, h, ltr=True):
grid_y = 0
for row_group in table.children:
for row in row_group.children:
for cell in row.children:
cells = reversed(row.children) if rtl else row.children
for cell in cells:
# No border inside of a cell with rowspan or colspan
for xx in range(cell.grid_x + 1, cell.grid_x + cell.colspan):
for yy in range(grid_y, grid_y + cell.rowspan):
Expand All @@ -1059,31 +1067,31 @@ def set_borders(box, x, y, w, h, ltr=True):
horizontal_borders[yy][xx] = strong_null_border
# The cell’s own borders
set_borders(cell, x=cell.grid_x, y=grid_y,
w=cell.colspan, h=cell.rowspan, ltr=ltr)
w=cell.colspan, h=cell.rowspan, rtl=rtl)
grid_y += 1

grid_y = 0
for row_group in table.children:
for row in row_group.children:
set_borders(row, x=0, y=grid_y, w=grid_width, h=1, ltr=ltr)
set_borders(row, x=0, y=grid_y, w=grid_width, h=1, rtl=rtl)
grid_y += 1

grid_y = 0
for row_group in table.children:
rowspan = len(row_group.children)
set_borders(row_group, x=0, y=grid_y, w=grid_width, h=rowspan, ltr=ltr)
set_borders(row_group, x=0, y=grid_y, w=grid_width, h=rowspan, rtl=rtl)
grid_y += rowspan

for column_group in table.column_groups:
for column in column_group.children:
set_borders(column, x=column.grid_x, y=0,
w=1, h=grid_height, ltr=ltr)
w=1, h=grid_height, rtl=rtl)

for column_group in table.column_groups:
set_borders(column_group, x=column_group.grid_x, y=0,
w=column_group.span, h=grid_height, ltr=ltr)
w=column_group.span, h=grid_height, rtl=rtl)

set_borders(table, x=0, y=0, w=grid_width, h=grid_height, ltr=ltr)
set_borders(table, x=0, y=0, w=grid_width, h=grid_height, rtl=rtl)

# Now that all conflicts are resolved, set transparent borders of
# the correct widths on each box. The actual border grid will be
Expand All @@ -1098,50 +1106,47 @@ def remove_borders(box):
set_border_used_width(box, 'bottom', 0)
set_border_used_width(box, 'left', 0)

def max_vertical_width(x, y1, y2):
return max(grid_row[x][1][1] for grid_row in vertical_borders[y1:y2])
def max_vertical_width(x, y, h):
return max(
width for grid_row in vertical_borders[y:y + h]
for _, (_, width, _) in [grid_row[x]])

def max_horizontal_width(x1, y, x2):
return max(width for _, (_, width, _) in horizontal_borders[y][x1:x2])
def max_horizontal_width(x, y, w):
return max(
width for _, (_, width, _) in horizontal_borders[y][x:x + w])

grid_y = 0
for row_group in table.children:
remove_borders(row_group)
for row in row_group.children:
remove_borders(row)
for cell in row.children:
x, y = cell.grid_x, grid_y
colspan, rowspan = cell.colspan, cell.rowspan
if table.style['direction'] == 'ltr':
top = max_horizontal_width(x, y, x + colspan)
bottom = max_horizontal_width(x, y + rowspan, x + colspan)
left = max_vertical_width(x, y, y + rowspan)
right = max_vertical_width(x + colspan, y, y + rowspan)
else:
top = max_horizontal_width(-colspan - x, y, -x or None)
bottom = max_horizontal_width(
-colspan - x, y + rowspan, -x or None)
left = max_vertical_width(-1 - colspan - x, y, y + rowspan)
right = max_vertical_width(-1 - x, y, y + rowspan)
set_border_used_width(cell, 'top', top)
set_border_used_width(cell, 'bottom', bottom)
set_border_used_width(cell, 'left', left)
set_border_used_width(cell, 'right', right)
set_border_used_width(cell, 'top', max_horizontal_width(
x=cell.grid_x, y=grid_y, w=cell.colspan))
set_border_used_width(cell, 'bottom', max_horizontal_width(
x=cell.grid_x, y=grid_y + cell.rowspan, w=cell.colspan))
set_border_used_width(cell, 'left', max_vertical_width(
x=cell.grid_x, y=grid_y, h=cell.rowspan))
set_border_used_width(cell, 'right', max_vertical_width(
x=cell.grid_x + cell.colspan, y=grid_y, h=cell.rowspan))
grid_y += 1

for column_group in table.column_groups:
remove_borders(column_group)
for column in column_group.children:
remove_borders(column)

set_border_used_width(table, 'top', max_horizontal_width(0, 0, grid_width))
set_border_used_width(table, 'top', max_horizontal_width(
x=0, y=0, w=grid_width))
set_border_used_width(table, 'bottom', max_horizontal_width(
0, grid_height, grid_width))
x=0, y=grid_height, w=grid_width))
# "UAs must compute an initial left and right border width for the table
# by examining the first and last cells in the first row of the table."
# https://www.w3.org/TR/CSS21/tables.html#collapsing-borders
# ... so h=1, not grid_height:
set_border_used_width(table, 'left', max_vertical_width(0, 0, 1))
set_border_used_width(table, 'right', max_vertical_width(grid_width, 0, 1))
set_border_used_width(table, 'left', max_vertical_width(
x=0, y=0, h=1))
set_border_used_width(table, 'right', max_vertical_width(
x=grid_width, y=0, h=1))

return vertical_borders, horizontal_borders

0 comments on commit a7f355c

Please sign in to comment.