From a7f355c83fb3775a65efa3a6252e3fc77efaffb5 Mon Sep 17 00:00:00 2001 From: kygoh Date: Tue, 13 Feb 2024 12:44:52 +0000 Subject: [PATCH] Avoid changing draw.py and boxes.py --- tests/draw/test_table.py | 3 -- weasyprint/draw.py | 14 +++++-- weasyprint/layout/float.py | 14 +++++-- weasyprint/layout/table.py | 85 ++++++++++++++++++++------------------ 4 files changed, 67 insertions(+), 49 deletions(-) diff --git a/tests/draw/test_table.py b/tests/draw/test_table.py index bce5d95a69..27ba8e42df 100644 --- a/tests/draw/test_table.py +++ b/tests/draw/test_table.py @@ -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(''' @@ -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(''' @@ -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(''' diff --git a/weasyprint/draw.py b/weasyprint/draw.py index 6f678358cf..9f38ee23b4 100644 --- a/weasyprint/draw.py +++ b/weasyprint/draw.py @@ -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): @@ -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) diff --git a/weasyprint/layout/float.py b/weasyprint/layout/float.py index daff903aa4..eaa2e51969 100644 --- a/weasyprint/layout/float.py +++ b/weasyprint/layout/float.py @@ -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 diff --git a/weasyprint/layout/table.py b/weasyprint/layout/table.py index cf330a9372..7b5d13937a 100644 --- a/weasyprint/layout/table.py +++ b/weasyprint/layout/table.py @@ -31,9 +31,16 @@ 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 @@ -41,7 +48,7 @@ def table_layout(context, table, bottom_space, skip_stack, containing_block, 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 @@ -1026,12 +1033,12 @@ 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) @@ -1039,7 +1046,7 @@ def set_borders(box, x, y, w, h, ltr=True): 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" @@ -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): @@ -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 @@ -1098,11 +1106,14 @@ 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: @@ -1110,23 +1121,14 @@ def max_horizontal_width(x1, y, x2): 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: @@ -1134,14 +1136,17 @@ def max_horizontal_width(x1, y, x2): 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