| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) |
| 3 * (C) 1997 Torben Weis (weis@kde.org) | 3 * (C) 1997 Torben Weis (weis@kde.org) |
| 4 * (C) 1998 Waldo Bastian (bastian@kde.org) | 4 * (C) 1998 Waldo Bastian (bastian@kde.org) |
| 5 * (C) 1999 Lars Knoll (knoll@kde.org) | 5 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. |
| 8 * All rights reserved. | 8 * All rights reserved. |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 static_assert(sizeof(LayoutTableCell) == sizeof(SameSizeAsLayoutTableCell), | 53 static_assert(sizeof(LayoutTableCell) == sizeof(SameSizeAsLayoutTableCell), |
| 54 "LayoutTableCell should stay small"); | 54 "LayoutTableCell should stay small"); |
| 55 static_assert(sizeof(CollapsedBorderValue) == 8, | 55 static_assert(sizeof(CollapsedBorderValue) == 8, |
| 56 "CollapsedBorderValue should stay small"); | 56 "CollapsedBorderValue should stay small"); |
| 57 | 57 |
| 58 LayoutTableCell::LayoutTableCell(Element* element) | 58 LayoutTableCell::LayoutTableCell(Element* element) |
| 59 : LayoutBlockFlow(element), | 59 : LayoutBlockFlow(element), |
| 60 absolute_column_index_(kUnsetColumnIndex), | 60 absolute_column_index_(kUnsetColumnIndex), |
| 61 cell_width_changed_(false), | 61 cell_width_changed_(false), |
| 62 collapsed_border_values_valid_(false), |
| 63 collapsed_borders_visually_changed_(false), |
| 62 intrinsic_padding_before_(0), | 64 intrinsic_padding_before_(0), |
| 63 intrinsic_padding_after_(0) { | 65 intrinsic_padding_after_(0) { |
| 64 // We only update the flags when notified of DOM changes in | 66 // We only update the flags when notified of DOM changes in |
| 65 // colSpanOrRowSpanChanged() so we need to set their initial values here in | 67 // colSpanOrRowSpanChanged() so we need to set their initial values here in |
| 66 // case something asks for colSpan()/rowSpan() before then. | 68 // case something asks for colSpan()/rowSpan() before then. |
| 67 UpdateColAndRowSpanFlags(); | 69 UpdateColAndRowSpanFlags(); |
| 68 } | 70 } |
| 69 | 71 |
| 70 LayoutTableCell::CollapsedBorderValues::CollapsedBorderValues( | 72 LayoutTableCell::CollapsedBorderValues::CollapsedBorderValues( |
| 71 const LayoutTableCell& layout_table_cell, | 73 const LayoutTableCell& layout_table_cell, |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 return HasSameDirectionAs(Table()) ? IsInStartColumn() : IsInEndColumn(); | 591 return HasSameDirectionAs(Table()) ? IsInStartColumn() : IsInEndColumn(); |
| 590 } | 592 } |
| 591 | 593 |
| 592 bool LayoutTableCell::HasEndBorderAdjoiningTable() const { | 594 bool LayoutTableCell::HasEndBorderAdjoiningTable() const { |
| 593 // The table direction determines the row direction. In mixed directionality, | 595 // The table direction determines the row direction. In mixed directionality, |
| 594 // we cannot guarantee that we have a common border with the table (think a | 596 // we cannot guarantee that we have a common border with the table (think a |
| 595 // ltr table with ltr end cell). | 597 // ltr table with ltr end cell). |
| 596 return HasSameDirectionAs(Table()) ? IsInEndColumn() : IsInStartColumn(); | 598 return HasSameDirectionAs(Table()) ? IsInEndColumn() : IsInStartColumn(); |
| 597 } | 599 } |
| 598 | 600 |
| 599 CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder( | 601 CSSPropertyID LayoutTableCell::ResolveBorderProperty( |
| 600 IncludeBorderColorOrNot include_color) const { | 602 CSSPropertyID property) const { |
| 603 return CSSProperty::ResolveDirectionAwareProperty( |
| 604 property, StyleForCellFlow().Direction(), |
| 605 StyleForCellFlow().GetWritingMode()); |
| 606 } |
| 607 |
| 608 CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder() const { |
| 601 LayoutTable* table = this->Table(); | 609 LayoutTable* table = this->Table(); |
| 610 LayoutTableCell* cell_before = table->CellBefore(this); |
| 611 // We can use the border shared with |cell_before| if it is valid. |
| 612 if (cell_before && cell_before->collapsed_border_values_valid_ && |
| 613 cell_before->RowIndex() == RowIndex()) { |
| 614 return cell_before->GetCollapsedBorderValues() |
| 615 ? cell_before->GetCollapsedBorderValues()->EndBorder() |
| 616 : CollapsedBorderValue(); |
| 617 } |
| 602 | 618 |
| 603 // For the start border, we need to check, in order of precedence: | 619 // For the start border, we need to check, in order of precedence: |
| 604 // (1) Our start border. | 620 // (1) Our start border. |
| 605 int start_color_property = include_color | 621 int start_color_property = |
| 606 ? CSSProperty::ResolveDirectionAwareProperty( | 622 ResolveBorderProperty(CSSPropertyWebkitBorderStartColor); |
| 607 CSSPropertyWebkitBorderStartColor, | |
| 608 StyleForCellFlow().Direction(), | |
| 609 StyleForCellFlow().GetWritingMode()) | |
| 610 : 0; | |
| 611 int end_color_property = | 623 int end_color_property = |
| 612 include_color | 624 ResolveBorderProperty(CSSPropertyWebkitBorderEndColor); |
| 613 ? CSSProperty::ResolveDirectionAwareProperty( | 625 CollapsedBorderValue result(Style()->BorderStart(), |
| 614 CSSPropertyWebkitBorderEndColor, StyleForCellFlow().Direction(), | 626 ResolveColor(start_color_property), |
| 615 StyleForCellFlow().GetWritingMode()) | 627 kBorderPrecedenceCell); |
| 616 : 0; | |
| 617 CollapsedBorderValue result( | |
| 618 Style()->BorderStart(), | |
| 619 include_color ? ResolveColor(start_color_property) : Color(), | |
| 620 kBorderPrecedenceCell); | |
| 621 | 628 |
| 622 // (2) The end border of the preceding cell. | 629 // (2) The end border of the preceding cell. |
| 623 LayoutTableCell* cell_before = table->CellBefore(this); | |
| 624 if (cell_before) { | 630 if (cell_before) { |
| 625 CollapsedBorderValue cell_before_adjoining_border = CollapsedBorderValue( | 631 CollapsedBorderValue cell_before_adjoining_border = CollapsedBorderValue( |
| 626 cell_before->BorderAdjoiningCellAfter(this), | 632 cell_before->BorderAdjoiningCellAfter(this), |
| 627 include_color ? cell_before->ResolveColor(end_color_property) : Color(), | 633 cell_before->ResolveColor(end_color_property), kBorderPrecedenceCell); |
| 628 kBorderPrecedenceCell); | |
| 629 // |result| should be the 2nd argument as |cellBefore| should win in case of | 634 // |result| should be the 2nd argument as |cellBefore| should win in case of |
| 630 // equality per CSS 2.1 (Border conflict resolution, point 4). | 635 // equality per CSS 2.1 (Border conflict resolution, point 4). |
| 631 result = ChooseBorder(cell_before_adjoining_border, result); | 636 result = ChooseBorder(cell_before_adjoining_border, result); |
| 632 if (!result.Exists()) | 637 if (!result.Exists()) |
| 633 return result; | 638 return result; |
| 634 } | 639 } |
| 635 | 640 |
| 636 bool start_border_adjoins_table = HasStartBorderAdjoiningTable(); | 641 bool start_border_adjoins_table = HasStartBorderAdjoiningTable(); |
| 637 if (start_border_adjoins_table) { | 642 if (start_border_adjoins_table) { |
| 638 // (3) Our row's start border. | 643 // (3) Our row's start border. |
| 639 result = ChooseBorder( | 644 result = ChooseBorder( |
| 640 result, CollapsedBorderValue( | 645 result, |
| 641 Row()->BorderAdjoiningStartCell(this), | 646 CollapsedBorderValue(Row()->BorderAdjoiningStartCell(this), |
| 642 include_color ? Parent()->ResolveColor(start_color_property) | 647 Parent()->ResolveColor(start_color_property), |
| 643 : Color(), | 648 kBorderPrecedenceRow)); |
| 644 kBorderPrecedenceRow)); | |
| 645 if (!result.Exists()) | 649 if (!result.Exists()) |
| 646 return result; | 650 return result; |
| 647 | 651 |
| 648 // (4) Our row group's start border. | 652 // (4) Our row group's start border. |
| 649 result = ChooseBorder( | 653 result = ChooseBorder( |
| 650 result, CollapsedBorderValue(Section()->BorderAdjoiningStartCell(this), | 654 result, |
| 651 include_color ? Section()->ResolveColor( | 655 CollapsedBorderValue(Section()->BorderAdjoiningStartCell(this), |
| 652 start_color_property) | 656 Section()->ResolveColor(start_color_property), |
| 653 : Color(), | 657 kBorderPrecedenceRowGroup)); |
| 654 kBorderPrecedenceRowGroup)); | |
| 655 if (!result.Exists()) | 658 if (!result.Exists()) |
| 656 return result; | 659 return result; |
| 657 } | 660 } |
| 658 | 661 |
| 659 // (5) Our column and column group's start borders. | 662 // (5) Our column and column group's start borders. |
| 660 LayoutTable::ColAndColGroup col_and_col_group = | 663 LayoutTable::ColAndColGroup col_and_col_group = |
| 661 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()); | 664 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()); |
| 662 if (col_and_col_group.colgroup && | 665 if (col_and_col_group.colgroup && |
| 663 col_and_col_group.adjoins_start_border_of_col_group) { | 666 col_and_col_group.adjoins_start_border_of_col_group) { |
| 664 // Only apply the colgroup's border if this cell touches the colgroup edge. | 667 // Only apply the colgroup's border if this cell touches the colgroup edge. |
| 665 result = ChooseBorder( | 668 result = ChooseBorder( |
| 666 result, | 669 result, |
| 667 CollapsedBorderValue( | 670 CollapsedBorderValue( |
| 668 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this), | 671 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this), |
| 669 include_color | 672 col_and_col_group.colgroup->ResolveColor(start_color_property), |
| 670 ? col_and_col_group.colgroup->ResolveColor(start_color_property) | |
| 671 : Color(), | |
| 672 kBorderPrecedenceColumnGroup)); | 673 kBorderPrecedenceColumnGroup)); |
| 673 if (!result.Exists()) | 674 if (!result.Exists()) |
| 674 return result; | 675 return result; |
| 675 } | 676 } |
| 676 if (col_and_col_group.col) { | 677 if (col_and_col_group.col) { |
| 677 // Always apply the col's border irrespective of whether this cell touches | 678 // Always apply the col's border irrespective of whether this cell touches |
| 678 // it. This is per HTML5: "For the purposes of the CSS table model, the col | 679 // it. This is per HTML5: "For the purposes of the CSS table model, the col |
| 679 // element is expected to be treated as if it "was present as many times as | 680 // element is expected to be treated as if it "was present as many times as |
| 680 // its span attribute specifies". | 681 // its span attribute specifies". |
| 681 result = ChooseBorder( | 682 result = ChooseBorder( |
| 682 result, CollapsedBorderValue( | 683 result, CollapsedBorderValue( |
| 683 col_and_col_group.col->BorderAdjoiningCellStartBorder(this), | 684 col_and_col_group.col->BorderAdjoiningCellStartBorder(this), |
| 684 include_color ? col_and_col_group.col->ResolveColor( | 685 col_and_col_group.col->ResolveColor(start_color_property), |
| 685 start_color_property) | |
| 686 : Color(), | |
| 687 kBorderPrecedenceColumn)); | 686 kBorderPrecedenceColumn)); |
| 688 if (!result.Exists()) | 687 if (!result.Exists()) |
| 689 return result; | 688 return result; |
| 690 } | 689 } |
| 691 | 690 |
| 692 // (6) The end border of the preceding column. | 691 // (6) The end border of the preceding column. |
| 693 if (cell_before) { | 692 if (cell_before) { |
| 694 LayoutTable::ColAndColGroup col_and_col_group = | 693 LayoutTable::ColAndColGroup col_and_col_group = |
| 695 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() - 1); | 694 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() - 1); |
| 696 // Only apply the colgroup's border if this cell touches the colgroup edge. | 695 // Only apply the colgroup's border if this cell touches the colgroup edge. |
| 697 if (col_and_col_group.colgroup && | 696 if (col_and_col_group.colgroup && |
| 698 col_and_col_group.adjoins_end_border_of_col_group) { | 697 col_and_col_group.adjoins_end_border_of_col_group) { |
| 699 result = ChooseBorder( | 698 result = ChooseBorder( |
| 700 CollapsedBorderValue( | 699 CollapsedBorderValue( |
| 701 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this), | 700 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this), |
| 702 include_color | 701 col_and_col_group.colgroup->ResolveColor(end_color_property), |
| 703 ? col_and_col_group.colgroup->ResolveColor(end_color_property) | |
| 704 : Color(), | |
| 705 kBorderPrecedenceColumnGroup), | 702 kBorderPrecedenceColumnGroup), |
| 706 result); | 703 result); |
| 707 if (!result.Exists()) | 704 if (!result.Exists()) |
| 708 return result; | 705 return result; |
| 709 } | 706 } |
| 710 // Always apply the col's border irrespective of whether this cell touches | 707 // Always apply the col's border irrespective of whether this cell touches |
| 711 // it. This is per HTML5: "For the purposes of the CSS table model, the col | 708 // it. This is per HTML5: "For the purposes of the CSS table model, the col |
| 712 // element is expected to be treated as if it "was present as many times as | 709 // element is expected to be treated as if it "was present as many times as |
| 713 // its span attribute specifies". | 710 // its span attribute specifies". |
| 714 if (col_and_col_group.col) { | 711 if (col_and_col_group.col) { |
| 715 result = ChooseBorder( | 712 result = ChooseBorder( |
| 716 CollapsedBorderValue( | 713 CollapsedBorderValue( |
| 717 col_and_col_group.col->BorderAdjoiningCellAfter(this), | 714 col_and_col_group.col->BorderAdjoiningCellAfter(this), |
| 718 include_color | 715 col_and_col_group.col->ResolveColor(end_color_property), |
| 719 ? col_and_col_group.col->ResolveColor(end_color_property) | |
| 720 : Color(), | |
| 721 kBorderPrecedenceColumn), | 716 kBorderPrecedenceColumn), |
| 722 result); | 717 result); |
| 723 if (!result.Exists()) | 718 if (!result.Exists()) |
| 724 return result; | 719 return result; |
| 725 } | 720 } |
| 726 } | 721 } |
| 727 | 722 |
| 728 if (start_border_adjoins_table) { | 723 if (start_border_adjoins_table) { |
| 729 // (7) The table's start border. | 724 // (7) The table's start border. |
| 730 result = ChooseBorder( | 725 result = ChooseBorder( |
| 731 result, | 726 result, CollapsedBorderValue(table->TableStartBorderAdjoiningCell(this), |
| 732 CollapsedBorderValue( | 727 table->ResolveColor(start_color_property), |
| 733 table->TableStartBorderAdjoiningCell(this), | 728 kBorderPrecedenceTable)); |
| 734 include_color ? table->ResolveColor(start_color_property) : Color(), | |
| 735 kBorderPrecedenceTable)); | |
| 736 if (!result.Exists()) | 729 if (!result.Exists()) |
| 737 return result; | 730 return result; |
| 738 } | 731 } |
| 739 | 732 |
| 740 return result; | 733 return result; |
| 741 } | 734 } |
| 742 | 735 |
| 743 CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder( | 736 CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder() const { |
| 744 IncludeBorderColorOrNot include_color) const { | |
| 745 LayoutTable* table = this->Table(); | 737 LayoutTable* table = this->Table(); |
| 746 // Note: We have to use the effective column information instead of whether we | 738 // Note: We have to use the effective column information instead of whether we |
| 747 // have a cell after as a table doesn't have to be regular (any row can have | 739 // have a cell after as a table doesn't have to be regular (any row can have |
| 748 // less cells than the total cell count). | 740 // less cells than the total cell count). |
| 749 bool is_end_column = table->AbsoluteColumnToEffectiveColumn( | 741 bool is_end_column = IsInEndColumn(); |
| 750 AbsoluteColumnIndex() + ColSpan() - 1) == | 742 LayoutTableCell* cell_after = |
| 751 table->NumEffectiveColumns() - 1; | 743 is_end_column ? nullptr : table->CellAfter(this); |
| 744 // We can use the border shared with |cell_after| if it is valid. |
| 745 if (cell_after && cell_after->collapsed_border_values_valid_ && |
| 746 cell_after->RowIndex() == RowIndex()) { |
| 747 return cell_after->GetCollapsedBorderValues() |
| 748 ? cell_after->GetCollapsedBorderValues()->StartBorder() |
| 749 : CollapsedBorderValue(); |
| 750 } |
| 752 | 751 |
| 753 // For end border, we need to check, in order of precedence: | 752 // For end border, we need to check, in order of precedence: |
| 754 // (1) Our end border. | 753 // (1) Our end border. |
| 755 int start_color_property = include_color | 754 int start_color_property = |
| 756 ? CSSProperty::ResolveDirectionAwareProperty( | 755 ResolveBorderProperty(CSSPropertyWebkitBorderStartColor); |
| 757 CSSPropertyWebkitBorderStartColor, | |
| 758 StyleForCellFlow().Direction(), | |
| 759 StyleForCellFlow().GetWritingMode()) | |
| 760 : 0; | |
| 761 int end_color_property = | 756 int end_color_property = |
| 762 include_color | 757 ResolveBorderProperty(CSSPropertyWebkitBorderEndColor); |
| 763 ? CSSProperty::ResolveDirectionAwareProperty( | |
| 764 CSSPropertyWebkitBorderEndColor, StyleForCellFlow().Direction(), | |
| 765 StyleForCellFlow().GetWritingMode()) | |
| 766 : 0; | |
| 767 CollapsedBorderValue result = CollapsedBorderValue( | 758 CollapsedBorderValue result = CollapsedBorderValue( |
| 768 Style()->BorderEnd(), | 759 Style()->BorderEnd(), ResolveColor(end_color_property), |
| 769 include_color ? ResolveColor(end_color_property) : Color(), | |
| 770 kBorderPrecedenceCell); | 760 kBorderPrecedenceCell); |
| 771 | 761 |
| 772 // (2) The start border of the following cell. | 762 // (2) The start border of the following cell. |
| 773 if (!is_end_column) { | 763 if (cell_after) { |
| 774 if (LayoutTableCell* cell_after = table->CellAfter(this)) { | 764 CollapsedBorderValue cell_after_adjoining_border = CollapsedBorderValue( |
| 775 CollapsedBorderValue cell_after_adjoining_border = CollapsedBorderValue( | 765 cell_after->BorderAdjoiningCellBefore(this), |
| 776 cell_after->BorderAdjoiningCellBefore(this), | 766 cell_after->ResolveColor(start_color_property), kBorderPrecedenceCell); |
| 777 include_color ? cell_after->ResolveColor(start_color_property) | 767 result = ChooseBorder(result, cell_after_adjoining_border); |
| 778 : Color(), | 768 if (!result.Exists()) |
| 779 kBorderPrecedenceCell); | 769 return result; |
| 780 result = ChooseBorder(result, cell_after_adjoining_border); | |
| 781 if (!result.Exists()) | |
| 782 return result; | |
| 783 } | |
| 784 } | 770 } |
| 785 | 771 |
| 786 bool end_border_adjoins_table = HasEndBorderAdjoiningTable(); | 772 bool end_border_adjoins_table = HasEndBorderAdjoiningTable(); |
| 787 if (end_border_adjoins_table) { | 773 if (end_border_adjoins_table) { |
| 788 // (3) Our row's end border. | 774 // (3) Our row's end border. |
| 789 result = ChooseBorder( | 775 result = ChooseBorder( |
| 790 result, CollapsedBorderValue( | 776 result, CollapsedBorderValue(Row()->BorderAdjoiningEndCell(this), |
| 791 Row()->BorderAdjoiningEndCell(this), | 777 Parent()->ResolveColor(end_color_property), |
| 792 include_color ? Parent()->ResolveColor(end_color_property) | 778 kBorderPrecedenceRow)); |
| 793 : Color(), | |
| 794 kBorderPrecedenceRow)); | |
| 795 if (!result.Exists()) | 779 if (!result.Exists()) |
| 796 return result; | 780 return result; |
| 797 | 781 |
| 798 // (4) Our row group's end border. | 782 // (4) Our row group's end border. |
| 799 result = ChooseBorder( | 783 result = ChooseBorder( |
| 800 result, CollapsedBorderValue( | 784 result, |
| 801 Section()->BorderAdjoiningEndCell(this), | 785 CollapsedBorderValue(Section()->BorderAdjoiningEndCell(this), |
| 802 include_color ? Section()->ResolveColor(end_color_property) | 786 Section()->ResolveColor(end_color_property), |
| 803 : Color(), | 787 kBorderPrecedenceRowGroup)); |
| 804 kBorderPrecedenceRowGroup)); | |
| 805 if (!result.Exists()) | 788 if (!result.Exists()) |
| 806 return result; | 789 return result; |
| 807 } | 790 } |
| 808 | 791 |
| 809 // (5) Our column and column group's end borders. | 792 // (5) Our column and column group's end borders. |
| 810 LayoutTable::ColAndColGroup col_and_col_group = | 793 LayoutTable::ColAndColGroup col_and_col_group = |
| 811 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan() - 1); | 794 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan() - 1); |
| 812 if (col_and_col_group.colgroup && | 795 if (col_and_col_group.colgroup && |
| 813 col_and_col_group.adjoins_end_border_of_col_group) { | 796 col_and_col_group.adjoins_end_border_of_col_group) { |
| 814 // Only apply the colgroup's border if this cell touches the colgroup edge. | 797 // Only apply the colgroup's border if this cell touches the colgroup edge. |
| 815 result = ChooseBorder( | 798 result = ChooseBorder( |
| 816 result, | 799 result, |
| 817 CollapsedBorderValue( | 800 CollapsedBorderValue( |
| 818 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this), | 801 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this), |
| 819 include_color | 802 col_and_col_group.colgroup->ResolveColor(end_color_property), |
| 820 ? col_and_col_group.colgroup->ResolveColor(end_color_property) | |
| 821 : Color(), | |
| 822 kBorderPrecedenceColumnGroup)); | 803 kBorderPrecedenceColumnGroup)); |
| 823 if (!result.Exists()) | 804 if (!result.Exists()) |
| 824 return result; | 805 return result; |
| 825 } | 806 } |
| 826 if (col_and_col_group.col) { | 807 if (col_and_col_group.col) { |
| 827 // Always apply the col's border irrespective of whether this cell touches | 808 // Always apply the col's border irrespective of whether this cell touches |
| 828 // it. This is per HTML5: "For the purposes of the CSS table model, the col | 809 // it. This is per HTML5: "For the purposes of the CSS table model, the col |
| 829 // element is expected to be treated as if it "was present as many times as | 810 // element is expected to be treated as if it "was present as many times as |
| 830 // its span attribute specifies". | 811 // its span attribute specifies". |
| 831 result = ChooseBorder( | 812 result = ChooseBorder( |
| 832 result, CollapsedBorderValue( | 813 result, CollapsedBorderValue( |
| 833 col_and_col_group.col->BorderAdjoiningCellEndBorder(this), | 814 col_and_col_group.col->BorderAdjoiningCellEndBorder(this), |
| 834 include_color ? col_and_col_group.col->ResolveColor( | 815 col_and_col_group.col->ResolveColor(end_color_property), |
| 835 end_color_property) | |
| 836 : Color(), | |
| 837 kBorderPrecedenceColumn)); | 816 kBorderPrecedenceColumn)); |
| 838 if (!result.Exists()) | 817 if (!result.Exists()) |
| 839 return result; | 818 return result; |
| 840 } | 819 } |
| 841 | 820 |
| 842 // (6) The start border of the next column. | 821 // (6) The start border of the next column. |
| 843 if (!is_end_column) { | 822 if (!is_end_column) { |
| 844 LayoutTable::ColAndColGroup col_and_col_group = | 823 LayoutTable::ColAndColGroup col_and_col_group = |
| 845 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan()); | 824 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan()); |
| 846 if (col_and_col_group.colgroup && | 825 if (col_and_col_group.colgroup && |
| 847 col_and_col_group.adjoins_start_border_of_col_group) { | 826 col_and_col_group.adjoins_start_border_of_col_group) { |
| 848 // Only apply the colgroup's border if this cell touches the colgroup | 827 // Only apply the colgroup's border if this cell touches the colgroup |
| 849 // edge. | 828 // edge. |
| 850 result = ChooseBorder( | 829 result = ChooseBorder( |
| 851 result, | 830 result, |
| 852 CollapsedBorderValue( | 831 CollapsedBorderValue( |
| 853 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this), | 832 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this), |
| 854 include_color ? col_and_col_group.colgroup->ResolveColor( | 833 col_and_col_group.colgroup->ResolveColor(start_color_property), |
| 855 start_color_property) | |
| 856 : Color(), | |
| 857 kBorderPrecedenceColumnGroup)); | 834 kBorderPrecedenceColumnGroup)); |
| 858 if (!result.Exists()) | 835 if (!result.Exists()) |
| 859 return result; | 836 return result; |
| 860 } | 837 } |
| 861 if (col_and_col_group.col) { | 838 if (col_and_col_group.col) { |
| 862 // Always apply the col's border irrespective of whether this cell touches | 839 // Always apply the col's border irrespective of whether this cell touches |
| 863 // it. This is per HTML5: "For the purposes of the CSS table model, the | 840 // it. This is per HTML5: "For the purposes of the CSS table model, the |
| 864 // col element is expected to be treated as if it "was present as many | 841 // col element is expected to be treated as if it "was present as many |
| 865 // times as its span attribute specifies". | 842 // times as its span attribute specifies". |
| 866 result = ChooseBorder( | 843 result = ChooseBorder( |
| 867 result, CollapsedBorderValue( | 844 result, CollapsedBorderValue( |
| 868 col_and_col_group.col->BorderAdjoiningCellBefore(this), | 845 col_and_col_group.col->BorderAdjoiningCellBefore(this), |
| 869 include_color ? col_and_col_group.col->ResolveColor( | 846 col_and_col_group.col->ResolveColor(start_color_property), |
| 870 start_color_property) | |
| 871 : Color(), | |
| 872 kBorderPrecedenceColumn)); | 847 kBorderPrecedenceColumn)); |
| 873 if (!result.Exists()) | 848 if (!result.Exists()) |
| 874 return result; | 849 return result; |
| 875 } | 850 } |
| 876 } | 851 } |
| 877 | 852 |
| 878 if (end_border_adjoins_table) { | 853 if (end_border_adjoins_table) { |
| 879 // (7) The table's end border. | 854 // (7) The table's end border. |
| 880 result = ChooseBorder( | 855 result = ChooseBorder( |
| 881 result, | 856 result, CollapsedBorderValue(table->TableEndBorderAdjoiningCell(this), |
| 882 CollapsedBorderValue( | 857 table->ResolveColor(end_color_property), |
| 883 table->TableEndBorderAdjoiningCell(this), | 858 kBorderPrecedenceTable)); |
| 884 include_color ? table->ResolveColor(end_color_property) : Color(), | |
| 885 kBorderPrecedenceTable)); | |
| 886 if (!result.Exists()) | 859 if (!result.Exists()) |
| 887 return result; | 860 return result; |
| 888 } | 861 } |
| 889 | 862 |
| 890 return result; | 863 return result; |
| 891 } | 864 } |
| 892 | 865 |
| 893 CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder( | 866 CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder() const { |
| 894 IncludeBorderColorOrNot include_color) const { | |
| 895 LayoutTable* table = this->Table(); | 867 LayoutTable* table = this->Table(); |
| 868 LayoutTableCell* prev_cell = table->CellAbove(this); |
| 869 // We can use the border shared with |prev_cell| if it is valid. |
| 870 if (prev_cell && prev_cell->collapsed_border_values_valid_ && |
| 871 prev_cell->AbsoluteColumnIndex() == AbsoluteColumnIndex()) { |
| 872 return prev_cell->GetCollapsedBorderValues() |
| 873 ? prev_cell->GetCollapsedBorderValues()->AfterBorder() |
| 874 : CollapsedBorderValue(); |
| 875 } |
| 896 | 876 |
| 897 // For before border, we need to check, in order of precedence: | 877 // For before border, we need to check, in order of precedence: |
| 898 // (1) Our before border. | 878 // (1) Our before border. |
| 899 int before_color_property = include_color | 879 int before_color_property = |
| 900 ? CSSProperty::ResolveDirectionAwareProperty( | 880 ResolveBorderProperty(CSSPropertyWebkitBorderBeforeColor); |
| 901 CSSPropertyWebkitBorderBeforeColor, | 881 int after_color_property = |
| 902 StyleForCellFlow().Direction(), | 882 ResolveBorderProperty(CSSPropertyWebkitBorderAfterColor); |
| 903 StyleForCellFlow().GetWritingMode()) | |
| 904 : 0; | |
| 905 int after_color_property = include_color | |
| 906 ? CSSProperty::ResolveDirectionAwareProperty( | |
| 907 CSSPropertyWebkitBorderAfterColor, | |
| 908 StyleForCellFlow().Direction(), | |
| 909 StyleForCellFlow().GetWritingMode()) | |
| 910 : 0; | |
| 911 CollapsedBorderValue result = CollapsedBorderValue( | 883 CollapsedBorderValue result = CollapsedBorderValue( |
| 912 Style()->BorderBefore(), | 884 Style()->BorderBefore(), ResolveColor(before_color_property), |
| 913 include_color ? ResolveColor(before_color_property) : Color(), | |
| 914 kBorderPrecedenceCell); | 885 kBorderPrecedenceCell); |
| 915 | 886 |
| 916 LayoutTableCell* prev_cell = table->CellAbove(this); | |
| 917 if (prev_cell) { | 887 if (prev_cell) { |
| 918 // (2) A before cell's after border. | 888 // (2) A before cell's after border. |
| 919 result = ChooseBorder( | 889 result = ChooseBorder( |
| 920 CollapsedBorderValue(prev_cell->Style()->BorderAfter(), | 890 CollapsedBorderValue(prev_cell->Style()->BorderAfter(), |
| 921 include_color | 891 prev_cell->ResolveColor(after_color_property), |
| 922 ? prev_cell->ResolveColor(after_color_property) | |
| 923 : Color(), | |
| 924 kBorderPrecedenceCell), | 892 kBorderPrecedenceCell), |
| 925 result); | 893 result); |
| 926 if (!result.Exists()) | 894 if (!result.Exists()) |
| 927 return result; | 895 return result; |
| 928 } | 896 } |
| 929 | 897 |
| 930 // (3) Our row's before border. | 898 // (3) Our row's before border. |
| 931 result = ChooseBorder( | 899 result = ChooseBorder( |
| 932 result, CollapsedBorderValue( | 900 result, |
| 933 Parent()->Style()->BorderBefore(), | 901 CollapsedBorderValue(Parent()->Style()->BorderBefore(), |
| 934 include_color ? Parent()->ResolveColor(before_color_property) | 902 Parent()->ResolveColor(before_color_property), |
| 935 : Color(), | 903 kBorderPrecedenceRow)); |
| 936 kBorderPrecedenceRow)); | |
| 937 if (!result.Exists()) | 904 if (!result.Exists()) |
| 938 return result; | 905 return result; |
| 939 | 906 |
| 940 // (4) The previous row's after border. | 907 // (4) The previous row's after border. |
| 941 if (prev_cell) { | 908 if (prev_cell) { |
| 942 LayoutObject* prev_row = nullptr; | 909 LayoutObject* prev_row = nullptr; |
| 943 if (prev_cell->Section() == Section()) | 910 if (prev_cell->Section() == Section()) |
| 944 prev_row = Parent()->PreviousSibling(); | 911 prev_row = Parent()->PreviousSibling(); |
| 945 else | 912 else |
| 946 prev_row = prev_cell->Section()->LastRow(); | 913 prev_row = prev_cell->Section()->LastRow(); |
| 947 | 914 |
| 948 if (prev_row) { | 915 if (prev_row) { |
| 949 result = ChooseBorder( | 916 result = ChooseBorder( |
| 950 CollapsedBorderValue( | 917 CollapsedBorderValue(prev_row->Style()->BorderAfter(), |
| 951 prev_row->Style()->BorderAfter(), | 918 prev_row->ResolveColor(after_color_property), |
| 952 include_color ? prev_row->ResolveColor(after_color_property) | 919 kBorderPrecedenceRow), |
| 953 : Color(), | |
| 954 kBorderPrecedenceRow), | |
| 955 result); | 920 result); |
| 956 if (!result.Exists()) | 921 if (!result.Exists()) |
| 957 return result; | 922 return result; |
| 958 } | 923 } |
| 959 } | 924 } |
| 960 | 925 |
| 961 // Now check row groups. | 926 // Now check row groups. |
| 962 LayoutTableSection* curr_section = Section(); | 927 LayoutTableSection* curr_section = Section(); |
| 963 if (!RowIndex()) { | 928 if (!RowIndex()) { |
| 964 // (5) Our row group's before border. | 929 // (5) Our row group's before border. |
| 965 result = ChooseBorder( | 930 result = ChooseBorder( |
| 966 result, CollapsedBorderValue(curr_section->Style()->BorderBefore(), | 931 result, |
| 967 include_color ? curr_section->ResolveColor( | 932 CollapsedBorderValue(curr_section->Style()->BorderBefore(), |
| 968 before_color_property) | 933 curr_section->ResolveColor(before_color_property), |
| 969 : Color(), | 934 kBorderPrecedenceRowGroup)); |
| 970 kBorderPrecedenceRowGroup)); | |
| 971 if (!result.Exists()) | 935 if (!result.Exists()) |
| 972 return result; | 936 return result; |
| 973 | 937 |
| 974 // (6) Previous row group's after border. | 938 // (6) Previous row group's after border. |
| 975 curr_section = table->SectionAbove(curr_section, kSkipEmptySections); | 939 curr_section = table->SectionAbove(curr_section, kSkipEmptySections); |
| 976 if (curr_section) { | 940 if (curr_section) { |
| 977 result = ChooseBorder( | 941 result = ChooseBorder( |
| 978 CollapsedBorderValue( | 942 CollapsedBorderValue(curr_section->Style()->BorderAfter(), |
| 979 curr_section->Style()->BorderAfter(), | 943 curr_section->ResolveColor(after_color_property), |
| 980 include_color ? curr_section->ResolveColor(after_color_property) | 944 kBorderPrecedenceRowGroup), |
| 981 : Color(), | |
| 982 kBorderPrecedenceRowGroup), | |
| 983 result); | 945 result); |
| 984 if (!result.Exists()) | 946 if (!result.Exists()) |
| 985 return result; | 947 return result; |
| 986 } | 948 } |
| 987 } | 949 } |
| 988 | 950 |
| 989 if (!curr_section) { | 951 if (!curr_section) { |
| 990 // (8) Our column and column group's before borders. | 952 // (8) Our column and column group's before borders. |
| 991 LayoutTableCol* col_elt = | 953 LayoutTableCol* col_elt = |
| 992 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()) | 954 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()) |
| 993 .InnermostColOrColGroup(); | 955 .InnermostColOrColGroup(); |
| 994 if (col_elt) { | 956 if (col_elt) { |
| 995 result = ChooseBorder( | 957 result = ChooseBorder( |
| 996 result, | 958 result, |
| 997 CollapsedBorderValue( | 959 CollapsedBorderValue(col_elt->Style()->BorderBefore(), |
| 998 col_elt->Style()->BorderBefore(), | 960 col_elt->ResolveColor(before_color_property), |
| 999 include_color ? col_elt->ResolveColor(before_color_property) | 961 kBorderPrecedenceColumn)); |
| 1000 : Color(), | |
| 1001 kBorderPrecedenceColumn)); | |
| 1002 if (!result.Exists()) | 962 if (!result.Exists()) |
| 1003 return result; | 963 return result; |
| 1004 if (LayoutTableCol* enclosing_column_group = | 964 if (LayoutTableCol* enclosing_column_group = |
| 1005 col_elt->EnclosingColumnGroup()) { | 965 col_elt->EnclosingColumnGroup()) { |
| 1006 result = ChooseBorder( | 966 result = ChooseBorder( |
| 1007 result, CollapsedBorderValue( | 967 result, |
| 1008 enclosing_column_group->Style()->BorderBefore(), | 968 CollapsedBorderValue( |
| 1009 include_color ? enclosing_column_group->ResolveColor( | 969 enclosing_column_group->Style()->BorderBefore(), |
| 1010 before_color_property) | 970 enclosing_column_group->ResolveColor(before_color_property), |
| 1011 : Color(), | 971 kBorderPrecedenceColumnGroup)); |
| 1012 kBorderPrecedenceColumnGroup)); | |
| 1013 if (!result.Exists()) | 972 if (!result.Exists()) |
| 1014 return result; | 973 return result; |
| 1015 } | 974 } |
| 1016 } | 975 } |
| 1017 | 976 |
| 1018 // (9) The table's before border. | 977 // (9) The table's before border. |
| 1019 result = ChooseBorder( | 978 result = ChooseBorder( |
| 1020 result, CollapsedBorderValue( | 979 result, CollapsedBorderValue(table->Style()->BorderBefore(), |
| 1021 table->Style()->BorderBefore(), | 980 table->ResolveColor(before_color_property), |
| 1022 include_color ? table->ResolveColor(before_color_property) | 981 kBorderPrecedenceTable)); |
| 1023 : Color(), | |
| 1024 kBorderPrecedenceTable)); | |
| 1025 if (!result.Exists()) | 982 if (!result.Exists()) |
| 1026 return result; | 983 return result; |
| 1027 } | 984 } |
| 1028 | 985 |
| 1029 return result; | 986 return result; |
| 1030 } | 987 } |
| 1031 | 988 |
| 1032 CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder( | 989 CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder() const { |
| 1033 IncludeBorderColorOrNot include_color) const { | |
| 1034 LayoutTable* table = this->Table(); | 990 LayoutTable* table = this->Table(); |
| 991 LayoutTableCell* next_cell = table->CellBelow(this); |
| 992 // We can use the border shared with |next_cell| if it is valid. |
| 993 if (next_cell && next_cell->collapsed_border_values_valid_ && |
| 994 next_cell->AbsoluteColumnIndex() == AbsoluteColumnIndex()) { |
| 995 return next_cell->GetCollapsedBorderValues() |
| 996 ? next_cell->GetCollapsedBorderValues()->BeforeBorder() |
| 997 : CollapsedBorderValue(); |
| 998 } |
| 1035 | 999 |
| 1036 // For after border, we need to check, in order of precedence: | 1000 // For after border, we need to check, in order of precedence: |
| 1037 // (1) Our after border. | 1001 // (1) Our after border. |
| 1038 int before_color_property = include_color | 1002 int before_color_property = |
| 1039 ? CSSProperty::ResolveDirectionAwareProperty( | 1003 ResolveBorderProperty(CSSPropertyWebkitBorderBeforeColor); |
| 1040 CSSPropertyWebkitBorderBeforeColor, | 1004 int after_color_property = |
| 1041 StyleForCellFlow().Direction(), | 1005 ResolveBorderProperty(CSSPropertyWebkitBorderAfterColor); |
| 1042 StyleForCellFlow().GetWritingMode()) | |
| 1043 : 0; | |
| 1044 int after_color_property = include_color | |
| 1045 ? CSSProperty::ResolveDirectionAwareProperty( | |
| 1046 CSSPropertyWebkitBorderAfterColor, | |
| 1047 StyleForCellFlow().Direction(), | |
| 1048 StyleForCellFlow().GetWritingMode()) | |
| 1049 : 0; | |
| 1050 CollapsedBorderValue result = CollapsedBorderValue( | 1006 CollapsedBorderValue result = CollapsedBorderValue( |
| 1051 Style()->BorderAfter(), | 1007 Style()->BorderAfter(), ResolveColor(after_color_property), |
| 1052 include_color ? ResolveColor(after_color_property) : Color(), | |
| 1053 kBorderPrecedenceCell); | 1008 kBorderPrecedenceCell); |
| 1054 | 1009 |
| 1055 LayoutTableCell* next_cell = table->CellBelow(this); | |
| 1056 if (next_cell) { | 1010 if (next_cell) { |
| 1057 // (2) An after cell's before border. | 1011 // (2) An after cell's before border. |
| 1058 result = ChooseBorder( | 1012 result = ChooseBorder( |
| 1059 result, CollapsedBorderValue(next_cell->Style()->BorderBefore(), | 1013 result, |
| 1060 include_color ? next_cell->ResolveColor( | 1014 CollapsedBorderValue(next_cell->Style()->BorderBefore(), |
| 1061 before_color_property) | 1015 next_cell->ResolveColor(before_color_property), |
| 1062 : Color(), | 1016 kBorderPrecedenceCell)); |
| 1063 kBorderPrecedenceCell)); | |
| 1064 if (!result.Exists()) | 1017 if (!result.Exists()) |
| 1065 return result; | 1018 return result; |
| 1066 } | 1019 } |
| 1067 | 1020 |
| 1068 // (3) Our row's after border. (FIXME: Deal with rowspan!) | 1021 // (3) Our row's after border. (FIXME: Deal with rowspan!) |
| 1069 result = ChooseBorder( | 1022 result = ChooseBorder( |
| 1070 result, CollapsedBorderValue( | 1023 result, CollapsedBorderValue(Parent()->Style()->BorderAfter(), |
| 1071 Parent()->Style()->BorderAfter(), | 1024 Parent()->ResolveColor(after_color_property), |
| 1072 include_color ? Parent()->ResolveColor(after_color_property) | 1025 kBorderPrecedenceRow)); |
| 1073 : Color(), | |
| 1074 kBorderPrecedenceRow)); | |
| 1075 if (!result.Exists()) | 1026 if (!result.Exists()) |
| 1076 return result; | 1027 return result; |
| 1077 | 1028 |
| 1078 // (4) The next row's before border. | 1029 // (4) The next row's before border. |
| 1079 if (next_cell) { | 1030 if (next_cell) { |
| 1080 result = ChooseBorder( | 1031 result = ChooseBorder( |
| 1081 result, | 1032 result, CollapsedBorderValue( |
| 1082 CollapsedBorderValue(next_cell->Parent()->Style()->BorderBefore(), | 1033 next_cell->Parent()->Style()->BorderBefore(), |
| 1083 include_color ? next_cell->Parent()->ResolveColor( | 1034 next_cell->Parent()->ResolveColor(before_color_property), |
| 1084 before_color_property) | 1035 kBorderPrecedenceRow)); |
| 1085 : Color(), | |
| 1086 kBorderPrecedenceRow)); | |
| 1087 if (!result.Exists()) | 1036 if (!result.Exists()) |
| 1088 return result; | 1037 return result; |
| 1089 } | 1038 } |
| 1090 | 1039 |
| 1091 // Now check row groups. | 1040 // Now check row groups. |
| 1092 LayoutTableSection* curr_section = Section(); | 1041 LayoutTableSection* curr_section = Section(); |
| 1093 if (RowIndex() + RowSpan() >= curr_section->NumRows()) { | 1042 if (RowIndex() + RowSpan() >= curr_section->NumRows()) { |
| 1094 // (5) Our row group's after border. | 1043 // (5) Our row group's after border. |
| 1095 result = ChooseBorder( | 1044 result = ChooseBorder( |
| 1096 result, CollapsedBorderValue(curr_section->Style()->BorderAfter(), | 1045 result, |
| 1097 include_color ? curr_section->ResolveColor( | 1046 CollapsedBorderValue(curr_section->Style()->BorderAfter(), |
| 1098 after_color_property) | 1047 curr_section->ResolveColor(after_color_property), |
| 1099 : Color(), | 1048 kBorderPrecedenceRowGroup)); |
| 1100 kBorderPrecedenceRowGroup)); | |
| 1101 if (!result.Exists()) | 1049 if (!result.Exists()) |
| 1102 return result; | 1050 return result; |
| 1103 | 1051 |
| 1104 // (6) Following row group's before border. | 1052 // (6) Following row group's before border. |
| 1105 curr_section = table->SectionBelow(curr_section, kSkipEmptySections); | 1053 curr_section = table->SectionBelow(curr_section, kSkipEmptySections); |
| 1106 if (curr_section) { | 1054 if (curr_section) { |
| 1107 result = ChooseBorder( | 1055 result = ChooseBorder( |
| 1108 result, | 1056 result, CollapsedBorderValue( |
| 1109 CollapsedBorderValue( | 1057 curr_section->Style()->BorderBefore(), |
| 1110 curr_section->Style()->BorderBefore(), | 1058 curr_section->ResolveColor(before_color_property), |
| 1111 include_color ? curr_section->ResolveColor(before_color_property) | 1059 kBorderPrecedenceRowGroup)); |
| 1112 : Color(), | |
| 1113 kBorderPrecedenceRowGroup)); | |
| 1114 if (!result.Exists()) | 1060 if (!result.Exists()) |
| 1115 return result; | 1061 return result; |
| 1116 } | 1062 } |
| 1117 } | 1063 } |
| 1118 | 1064 |
| 1119 if (!curr_section) { | 1065 if (!curr_section) { |
| 1120 // (8) Our column and column group's after borders. | 1066 // (8) Our column and column group's after borders. |
| 1121 LayoutTableCol* col_elt = | 1067 LayoutTableCol* col_elt = |
| 1122 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()) | 1068 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()) |
| 1123 .InnermostColOrColGroup(); | 1069 .InnermostColOrColGroup(); |
| 1124 if (col_elt) { | 1070 if (col_elt) { |
| 1125 result = ChooseBorder( | 1071 result = ChooseBorder( |
| 1126 result, CollapsedBorderValue(col_elt->Style()->BorderAfter(), | 1072 result, |
| 1127 include_color ? col_elt->ResolveColor( | 1073 CollapsedBorderValue(col_elt->Style()->BorderAfter(), |
| 1128 after_color_property) | 1074 col_elt->ResolveColor(after_color_property), |
| 1129 : Color(), | 1075 kBorderPrecedenceColumn)); |
| 1130 kBorderPrecedenceColumn)); | |
| 1131 if (!result.Exists()) | 1076 if (!result.Exists()) |
| 1132 return result; | 1077 return result; |
| 1133 if (LayoutTableCol* enclosing_column_group = | 1078 if (LayoutTableCol* enclosing_column_group = |
| 1134 col_elt->EnclosingColumnGroup()) { | 1079 col_elt->EnclosingColumnGroup()) { |
| 1135 result = ChooseBorder( | 1080 result = ChooseBorder( |
| 1136 result, CollapsedBorderValue( | 1081 result, |
| 1137 enclosing_column_group->Style()->BorderAfter(), | 1082 CollapsedBorderValue( |
| 1138 include_color ? enclosing_column_group->ResolveColor( | 1083 enclosing_column_group->Style()->BorderAfter(), |
| 1139 after_color_property) | 1084 enclosing_column_group->ResolveColor(after_color_property), |
| 1140 : Color(), | 1085 kBorderPrecedenceColumnGroup)); |
| 1141 kBorderPrecedenceColumnGroup)); | |
| 1142 if (!result.Exists()) | 1086 if (!result.Exists()) |
| 1143 return result; | 1087 return result; |
| 1144 } | 1088 } |
| 1145 } | 1089 } |
| 1146 | 1090 |
| 1147 // (9) The table's after border. | 1091 // (9) The table's after border. |
| 1148 result = ChooseBorder( | 1092 result = ChooseBorder( |
| 1149 result, | 1093 result, CollapsedBorderValue(table->Style()->BorderAfter(), |
| 1150 CollapsedBorderValue( | 1094 table->ResolveColor(after_color_property), |
| 1151 table->Style()->BorderAfter(), | 1095 kBorderPrecedenceTable)); |
| 1152 include_color ? table->ResolveColor(after_color_property) : Color(), | |
| 1153 kBorderPrecedenceTable)); | |
| 1154 if (!result.Exists()) | 1096 if (!result.Exists()) |
| 1155 return result; | 1097 return result; |
| 1156 } | 1098 } |
| 1157 | 1099 |
| 1158 return result; | 1100 return result; |
| 1159 } | 1101 } |
| 1160 | 1102 |
| 1161 LayoutUnit LayoutTableCell::BorderLeft() const { | 1103 LayoutUnit LayoutTableCell::BorderLeft() const { |
| 1162 return Table()->CollapseBorders() ? CollapsedBorderHalfLeft(false) | 1104 return Table()->CollapseBorders() ? CollapsedBorderHalfLeft(false) |
| 1163 : LayoutBlockFlow::BorderLeft(); | 1105 : LayoutBlockFlow::BorderLeft(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 return style_for_cell_flow.IsFlippedBlocksWritingMode() | 1185 return style_for_cell_flow.IsFlippedBlocksWritingMode() |
| 1244 ? CollapsedBorderHalfBefore(outer) | 1186 ? CollapsedBorderHalfBefore(outer) |
| 1245 : CollapsedBorderHalfAfter(outer); | 1187 : CollapsedBorderHalfAfter(outer); |
| 1246 } | 1188 } |
| 1247 return style_for_cell_flow.IsLeftToRightDirection() | 1189 return style_for_cell_flow.IsLeftToRightDirection() |
| 1248 ? CollapsedBorderHalfEnd(outer) | 1190 ? CollapsedBorderHalfEnd(outer) |
| 1249 : CollapsedBorderHalfStart(outer); | 1191 : CollapsedBorderHalfStart(outer); |
| 1250 } | 1192 } |
| 1251 | 1193 |
| 1252 LayoutUnit LayoutTableCell::CollapsedBorderHalfStart(bool outer) const { | 1194 LayoutUnit LayoutTableCell::CollapsedBorderHalfStart(bool outer) const { |
| 1253 CollapsedBorderValue border = | 1195 UpdateCollapsedBorderValues(); |
| 1254 ComputeCollapsedStartBorder(kDoNotIncludeBorderColor); | 1196 const auto* collapsed_border_values = this->GetCollapsedBorderValues(); |
| 1197 if (!collapsed_border_values) |
| 1198 return LayoutUnit(); |
| 1199 |
| 1200 const auto& border = collapsed_border_values->StartBorder(); |
| 1255 if (border.Exists()) { | 1201 if (border.Exists()) { |
| 1256 return LayoutUnit( | 1202 return LayoutUnit( |
| 1257 (border.Width() + | 1203 (border.Width() + |
| 1258 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 1 : 0)) / | 1204 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 1 : 0)) / |
| 1259 2); // Give the extra pixel to top and left. | 1205 2); // Give the extra pixel to top and left. |
| 1260 } | 1206 } |
| 1261 return LayoutUnit(); | 1207 return LayoutUnit(); |
| 1262 } | 1208 } |
| 1263 | 1209 |
| 1264 LayoutUnit LayoutTableCell::CollapsedBorderHalfEnd(bool outer) const { | 1210 LayoutUnit LayoutTableCell::CollapsedBorderHalfEnd(bool outer) const { |
| 1265 CollapsedBorderValue border = | 1211 UpdateCollapsedBorderValues(); |
| 1266 ComputeCollapsedEndBorder(kDoNotIncludeBorderColor); | 1212 const auto* collapsed_border_values = this->GetCollapsedBorderValues(); |
| 1213 if (!collapsed_border_values) |
| 1214 return LayoutUnit(); |
| 1215 |
| 1216 const auto& border = collapsed_border_values->EndBorder(); |
| 1267 if (border.Exists()) { | 1217 if (border.Exists()) { |
| 1268 return LayoutUnit( | 1218 return LayoutUnit( |
| 1269 (border.Width() + | 1219 (border.Width() + |
| 1270 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 0 : 1)) / | 1220 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 0 : 1)) / |
| 1271 2); | 1221 2); |
| 1272 } | 1222 } |
| 1273 return LayoutUnit(); | 1223 return LayoutUnit(); |
| 1274 } | 1224 } |
| 1275 | 1225 |
| 1276 LayoutUnit LayoutTableCell::CollapsedBorderHalfBefore(bool outer) const { | 1226 LayoutUnit LayoutTableCell::CollapsedBorderHalfBefore(bool outer) const { |
| 1277 CollapsedBorderValue border = | 1227 UpdateCollapsedBorderValues(); |
| 1278 ComputeCollapsedBeforeBorder(kDoNotIncludeBorderColor); | 1228 const auto* collapsed_border_values = this->GetCollapsedBorderValues(); |
| 1229 if (!collapsed_border_values) |
| 1230 return LayoutUnit(); |
| 1231 |
| 1232 const auto& border = collapsed_border_values->BeforeBorder(); |
| 1279 if (border.Exists()) { | 1233 if (border.Exists()) { |
| 1280 return LayoutUnit( | 1234 return LayoutUnit( |
| 1281 (border.Width() + | 1235 (border.Width() + |
| 1282 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / | 1236 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / |
| 1283 2); // Give the extra pixel to top and left. | 1237 2); // Give the extra pixel to top and left. |
| 1284 } | 1238 } |
| 1285 return LayoutUnit(); | 1239 return LayoutUnit(); |
| 1286 } | 1240 } |
| 1287 | 1241 |
| 1288 LayoutUnit LayoutTableCell::CollapsedBorderHalfAfter(bool outer) const { | 1242 LayoutUnit LayoutTableCell::CollapsedBorderHalfAfter(bool outer) const { |
| 1289 CollapsedBorderValue border = | 1243 UpdateCollapsedBorderValues(); |
| 1290 ComputeCollapsedAfterBorder(kDoNotIncludeBorderColor); | 1244 const auto* collapsed_border_values = this->GetCollapsedBorderValues(); |
| 1245 if (!collapsed_border_values) |
| 1246 return LayoutUnit(); |
| 1247 |
| 1248 const auto& border = collapsed_border_values->AfterBorder(); |
| 1291 if (border.Exists()) { | 1249 if (border.Exists()) { |
| 1292 return LayoutUnit( | 1250 return LayoutUnit( |
| 1293 (border.Width() + | 1251 (border.Width() + |
| 1294 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / | 1252 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / |
| 1295 2); | 1253 2); |
| 1296 } | 1254 } |
| 1297 return LayoutUnit(); | 1255 return LayoutUnit(); |
| 1298 } | 1256 } |
| 1299 | 1257 |
| 1300 void LayoutTableCell::Paint(const PaintInfo& paint_info, | 1258 void LayoutTableCell::Paint(const PaintInfo& paint_info, |
| 1301 const LayoutPoint& paint_offset) const { | 1259 const LayoutPoint& paint_offset) const { |
| 1302 TableCellPainter(*this).Paint(paint_info, paint_offset); | 1260 TableCellPainter(*this).Paint(paint_info, paint_offset); |
| 1303 } | 1261 } |
| 1304 | 1262 |
| 1263 void LayoutTableCell::UpdateCollapsedBorderValues() const { |
| 1264 Table()->InvalidateCollapsedBordersForAllCellsIfNeeded(); |
| 1265 if (collapsed_border_values_valid_) |
| 1266 return; |
| 1267 |
| 1268 collapsed_border_values_valid_ = true; |
| 1269 |
| 1270 if (!Table()->CollapseBorders()) { |
| 1271 if (collapsed_border_values_) { |
| 1272 collapsed_borders_visually_changed_ = true; |
| 1273 collapsed_border_values_ = nullptr; |
| 1274 } |
| 1275 return; |
| 1276 } |
| 1277 |
| 1278 CollapsedBorderValues new_values( |
| 1279 *this, ComputeCollapsedStartBorder(), ComputeCollapsedEndBorder(), |
| 1280 ComputeCollapsedBeforeBorder(), ComputeCollapsedAfterBorder()); |
| 1281 |
| 1282 // We need to save collapsed border if has a non-zero width even if it's |
| 1283 // invisible because the width affects table layout. |
| 1284 if (!new_values.StartBorder().Width() && !new_values.EndBorder().Width() && |
| 1285 !new_values.BeforeBorder().Width() && !new_values.AfterBorder().Width()) { |
| 1286 if (collapsed_border_values_) { |
| 1287 collapsed_borders_visually_changed_ = true; |
| 1288 collapsed_border_values_ = nullptr; |
| 1289 } |
| 1290 return; |
| 1291 } |
| 1292 |
| 1293 if (!collapsed_border_values_) { |
| 1294 collapsed_borders_visually_changed_ = true; |
| 1295 collapsed_border_values_ = WTF::WrapUnique(new CollapsedBorderValues( |
| 1296 *this, new_values.StartBorder(), new_values.EndBorder(), |
| 1297 new_values.BeforeBorder(), new_values.AfterBorder())); |
| 1298 return; |
| 1299 } |
| 1300 |
| 1301 // We check VisuallyEquals so that the table cell is invalidated only if a |
| 1302 // changed collapsed border is visible in the first place. |
| 1303 if (!collapsed_border_values_->StartBorder().VisuallyEquals( |
| 1304 new_values.StartBorder()) || |
| 1305 !collapsed_border_values_->EndBorder().VisuallyEquals( |
| 1306 new_values.EndBorder()) || |
| 1307 !collapsed_border_values_->BeforeBorder().VisuallyEquals( |
| 1308 new_values.BeforeBorder()) || |
| 1309 !collapsed_border_values_->AfterBorder().VisuallyEquals( |
| 1310 new_values.AfterBorder())) { |
| 1311 collapsed_border_values_->SetCollapsedBorderValues(new_values); |
| 1312 collapsed_borders_visually_changed_ = true; |
| 1313 } |
| 1314 } |
| 1315 |
| 1305 static void AddBorderStyle(LayoutTable::CollapsedBorderValues& border_values, | 1316 static void AddBorderStyle(LayoutTable::CollapsedBorderValues& border_values, |
| 1306 CollapsedBorderValue border_value) { | 1317 CollapsedBorderValue border_value) { |
| 1307 if (!border_value.IsVisible()) | 1318 if (!border_value.IsVisible()) |
| 1308 return; | 1319 return; |
| 1309 size_t count = border_values.size(); | 1320 size_t count = border_values.size(); |
| 1310 for (size_t i = 0; i < count; ++i) { | 1321 for (size_t i = 0; i < count; ++i) { |
| 1311 if (border_values[i].IsSameIgnoringColor(border_value)) | 1322 if (border_values[i].IsSameIgnoringColor(border_value)) |
| 1312 return; | 1323 return; |
| 1313 } | 1324 } |
| 1314 border_values.push_back(border_value); | 1325 border_values.push_back(border_value); |
| 1315 } | 1326 } |
| 1316 | 1327 |
| 1317 void LayoutTableCell::CollectCollapsedBorderValues( | 1328 void LayoutTableCell::CollectCollapsedBorderValues( |
| 1318 LayoutTable::CollapsedBorderValues& border_values) { | 1329 LayoutTable::CollapsedBorderValues& border_values) { |
| 1319 CollapsedBorderValues new_values( | 1330 UpdateCollapsedBorderValues(); |
| 1320 *this, ComputeCollapsedStartBorder(), ComputeCollapsedEndBorder(), | |
| 1321 ComputeCollapsedBeforeBorder(), ComputeCollapsedAfterBorder()); | |
| 1322 | |
| 1323 bool changed = false; | |
| 1324 if (!new_values.StartBorder().IsVisible() && | |
| 1325 !new_values.EndBorder().IsVisible() && | |
| 1326 !new_values.BeforeBorder().IsVisible() && | |
| 1327 !new_values.AfterBorder().IsVisible()) { | |
| 1328 changed = !!collapsed_border_values_; | |
| 1329 collapsed_border_values_ = nullptr; | |
| 1330 } else if (!collapsed_border_values_) { | |
| 1331 changed = true; | |
| 1332 collapsed_border_values_ = WTF::WrapUnique(new CollapsedBorderValues( | |
| 1333 *this, new_values.StartBorder(), new_values.EndBorder(), | |
| 1334 new_values.BeforeBorder(), new_values.AfterBorder())); | |
| 1335 } else { | |
| 1336 // We check visuallyEquals so that the table cell is invalidated only if a | |
| 1337 // changed collapsed border is visible in the first place. | |
| 1338 changed = !collapsed_border_values_->StartBorder().VisuallyEquals( | |
| 1339 new_values.StartBorder()) || | |
| 1340 !collapsed_border_values_->EndBorder().VisuallyEquals( | |
| 1341 new_values.EndBorder()) || | |
| 1342 !collapsed_border_values_->BeforeBorder().VisuallyEquals( | |
| 1343 new_values.BeforeBorder()) || | |
| 1344 !collapsed_border_values_->AfterBorder().VisuallyEquals( | |
| 1345 new_values.AfterBorder()); | |
| 1346 if (changed) | |
| 1347 collapsed_border_values_->SetCollapsedBorderValues(new_values); | |
| 1348 } | |
| 1349 | 1331 |
| 1350 // If collapsed borders changed, invalidate the cell's display item client on | 1332 // If collapsed borders changed, invalidate the cell's display item client on |
| 1351 // the table's backing. | 1333 // the table's backing. |
| 1352 // TODO(crbug.com/451090#c5): Need a way to invalidate/repaint the borders | 1334 // TODO(crbug.com/451090#c5): Need a way to invalidate/repaint the borders |
| 1353 // only. | 1335 // only. |
| 1354 if (changed) { | 1336 if (collapsed_borders_visually_changed_) { |
| 1355 ObjectPaintInvalidator(*Table()) | 1337 ObjectPaintInvalidator(*Table()) |
| 1356 .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient( | 1338 .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient( |
| 1357 *this, kPaintInvalidationStyleChange); | 1339 *this, kPaintInvalidationStyleChange); |
| 1340 collapsed_borders_visually_changed_ = false; |
| 1358 } | 1341 } |
| 1359 | 1342 |
| 1360 AddBorderStyle(border_values, new_values.StartBorder()); | 1343 if (!collapsed_border_values_) |
| 1361 AddBorderStyle(border_values, new_values.EndBorder()); | 1344 return; |
| 1362 AddBorderStyle(border_values, new_values.BeforeBorder()); | 1345 |
| 1363 AddBorderStyle(border_values, new_values.AfterBorder()); | 1346 AddBorderStyle(border_values, collapsed_border_values_->StartBorder()); |
| 1347 AddBorderStyle(border_values, collapsed_border_values_->EndBorder()); |
| 1348 AddBorderStyle(border_values, collapsed_border_values_->BeforeBorder()); |
| 1349 AddBorderStyle(border_values, collapsed_border_values_->AfterBorder()); |
| 1364 } | 1350 } |
| 1365 | 1351 |
| 1366 void LayoutTableCell::SortCollapsedBorderValues( | 1352 void LayoutTableCell::SortCollapsedBorderValues( |
| 1367 LayoutTable::CollapsedBorderValues& border_values) { | 1353 LayoutTable::CollapsedBorderValues& border_values) { |
| 1368 std::sort(border_values.begin(), border_values.end(), CompareBorders); | 1354 std::sort(border_values.begin(), border_values.end(), CompareBorders); |
| 1369 } | 1355 } |
| 1370 | 1356 |
| 1371 void LayoutTableCell::PaintBoxDecorationBackground( | 1357 void LayoutTableCell::PaintBoxDecorationBackground( |
| 1372 const PaintInfo& paint_info, | 1358 const PaintInfo& paint_info, |
| 1373 const LayoutPoint& paint_offset) const { | 1359 const LayoutPoint& paint_offset) const { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 } | 1471 } |
| 1486 | 1472 |
| 1487 bool LayoutTableCell::HasLineIfEmpty() const { | 1473 bool LayoutTableCell::HasLineIfEmpty() const { |
| 1488 if (GetNode() && HasEditableStyle(*GetNode())) | 1474 if (GetNode() && HasEditableStyle(*GetNode())) |
| 1489 return true; | 1475 return true; |
| 1490 | 1476 |
| 1491 return LayoutBlock::HasLineIfEmpty(); | 1477 return LayoutBlock::HasLineIfEmpty(); |
| 1492 } | 1478 } |
| 1493 | 1479 |
| 1494 } // namespace blink | 1480 } // namespace blink |
| OLD | NEW |